#include "GameServer.h"
#include "ui_GameServer.h"

#include "Database.h"

//#include <QLinkedList>
//#include <QMessageBox>


#include "_Global/Mysql/Mysql.h"
#include "_Global/Socket/Server/IOCPDllClass/UDPIOCP_Pleafles.h"


#include <QtSql>
#include <QSqlQuery>
//#include <QByteArray>
#include <QThread>
#include <QCloseEvent>




int _GameGroup::StartGame(int type)
{
    if(m_pClientsGroupInfo->m_mapPlayingClients.isEmpty())
        return -1;

    if(m_pClientsGroupInfo->m_flagStatus & _ClientsGroupInfo::Status_Playing)
        return -2;

    //int userCount = m_mapPlayingClients.count();

    if(type == 0)
    {
        //是否可以开始游戏
        QMap<qint32, _ClientInfo*>::const_iterator ii;
        for(ii = m_pClientsGroupInfo->m_mapPlayingClients.constBegin(); ii != m_pClientsGroupInfo->m_mapPlayingClients.constEnd(); ++ii)
        {
            switch ((*ii)->m_ClientGroupStatus)
            {
            case _ClientGroupStatus::GroupStatus_Readying:
                continue;
            case _ClientGroupStatus::GroupStatus_Waiting:

                //如果是房主
                /*if(m_pClientsGroupInfo->m_pGroupMaster == (*ii))
                {
                    (*ii)->m_ClientGroupStatus = _ClientGroupStatus::GroupStatus_Readying;
                }
                else
                */
                {
                    emit s_Debug(tr("[GameGroup]有人没准备好"));
                    return -3;
                }

            case _ClientGroupStatus::GroupStatus_ReadyToWatch:
            default:
                emit s_Critical(tr("[!GameGroup]GameStart状态错误:%1").arg((*ii)->m_ClientGroupStatus));
                return -4;
            }
        }
    }



    //emit s_Debug(tr("[GameGroup]可以开始游戏"));
    //Debug(tr("[GameGroup]随机数种子:%1").arg(lmsSrand(-1)));
    /*
     * 1.设置每个用户status
     * 2.设置游戏status
     * 3.设置Master
     * 4.发送m_nMyID(GameID),玩家数,角色,武将信息!!!???
    */

    //QList<_Player::JiaoSe> playerJiaoSeList;  //GameID代替了

    //设置变量
    //m_pClientsGroupInfo->m_flagStatus |= _ClientsGroupInfo::Status_Locked;
    m_pClientsGroupInfo->m_flagStatus |= _ClientsGroupInfo::Status_Playing;
    //m_nPlayerCount = m_pClientsGroupInfo->m_GroupInfo.nClientsMaxCount;
    //m_bMaster = true;
    //m_nMyID = -1;
    //m_Producer.init();

    //emit s_Debug(tr("[GameGroup]游戏开始数据群发完毕,等待客户Init后开始游戏线程"));
    emit s_Info(tr("[GameGroup]房间游戏初始化中:%1(%2)").arg(m_nGroupID).arg(m_pClientsGroupInfo->m_uuid.toString()));

    GameInit();


    //QVector<quint32> playerGameIDArray(m_nPlayerCount);
    //QVector<qint16> playerDuiWuArray(m_nPlayerCount);

    //随机排列位置,设置角色
    /*qint32 temp[GAME_MAX_NUM_PLAYER];
    if(!GetDifferentNumber(0,m_nPlayerCount,temp,m_nPlayerCount,sizeof(qint32)))
    {
        m_pClientsGroupInfo->m_flagStatus = _ClientsGroupInfo::Status_Normal;
        return -1;
    }*/


    //发送
    QByteArray ba = m_pClientsGroupInfo->m_pIOCP->newSendData(TRANSMIT_GAME_TYPE);
    QDataStream ds(&ba,QIODevice::ReadWrite);
    ds.device()->seek(ba.size());
    ds << (qint16)GAME_DATA
       << (qint16)GAME_DATA_STARTGAME
       << (qint16)GAME_DATA_STARTGAME_SUCCESS
       << (bool)false
       //<< (qint16)m_nPlayerCount
       //<< playerGameIDArray
       //<< playerDuiWuArray
       //<< playerJiaoSeList
          ;
    m_pClientsGroupInfo->m_pIOCP->CorrectDataLength(ba);
    m_pClientsGroupInfo->SendToGroupAllClients(ba, nullptr, -1);
    //sendToAllClientInGroup(ba, pClientInfo);

    //qDebug() << "[GameGroup]playerGameIDArray:" << playerGameIDArray;


    //this->start();

    emit s_Info(tr("[GameServer]房间游戏开始:%1(%2),%3(%4,%5)")
                .arg(m_nGroupID)
                .arg(m_pClientsGroupInfo->m_uuid.toString())
                .arg(m_pClientsGroupInfo->m_mapAllClients.count())
                .arg(m_pClientsGroupInfo->m_mapPlayingClients.count())
                .arg(m_pClientsGroupInfo->m_mapWatchingClients.count())
                );
    GameStart(false);


    return 0;
}











GameServer::GameServer(QWidget *parent) :
    QWidget(parent),
    m_nFrameSendInterval(-1),
    ui(new Ui::GameServer)
{
    ui->setupUi(this);
    ui->pushButtonClose->setEnabled(false);
    this->setWindowTitle("宠物世界服务器2.0  --made by 深林孤鹰");
    ui->textDebug->document()->setMaximumBlockCount(500);
    this->show();



    connect(ui->pushButtonStart,&QPushButton::clicked,this,[=](){
        if(!Start())
        {
            return;
        }

        ui->pushButtonStart->setEnabled(false);
        ui->pushButtonClose->setEnabled(true);
        ui->pushButtonClose->setFocus();
    });

    connect(ui->pushButtonClose,&QPushButton::clicked,this,[=](){
        Stop();

        ui->pushButtonStart->setEnabled(true);
        ui->pushButtonClose->setEnabled(false);
        ui->pushButtonStart->setFocus();
    });

    connect(ui->pushButtonUserList,&QPushButton::clicked,this,[=](){

        QMap<qint32,_ClientInfo*>::const_iterator ii;
        for(ii = m_Server.m_mapAllClients.constBegin(); ii != m_Server.m_mapAllClients.constEnd(); ii++)
        {
            Info(tr("客户:socketID:%1;UserName:%2;Address(%3,%4)")
                 .arg(ii.value()->m_SocketContext.nSocketID)
                 .arg(((_GameUserData*)((*ii)->m_pClientExtraData))->m_strUserName)
                 .arg((int)(ii.value()))
                 .arg((int)(ii.value()->m_SocketContext.pIOCPSocketContext))
                 );
        }
        Info(tr("共 %1 个").arg(m_Server.m_mapAllClients.count()));
    });

    connect(ui->pushButtonTick,&QPushButton::clicked,this,[=](){
        qint32 clientID = ui->lineEditUserContextID->text().toInt();
        _ClientInfo *pClientInfo = m_Server.m_mapAllClients.value(clientID, nullptr);
        if(pClientInfo != nullptr)
        {
            ExitGroup(pClientInfo, false, false);
            DisconnectClient(pClientInfo, 0, true);
            Info(tr("成功断开%1").arg((int)pClientInfo));
        }
        else
        {
            Info(tr("没有%1").arg(clientID));
        }
    });

    connect(ui->pushButtonCloseGroup,&QPushButton::clicked,this,[=](){
        qint32 groupID = ui->lineEditGroupID->text().toInt();
        QUuid uuid = m_hashNumberGroups.value(groupID, QUuid());
        CloseGroup(m_Server.GetGroup(uuid));
    });

    //发送信息包
    connect(ui->pushButtonHeart,&QPushButton::clicked,this,[=](){

        qint32 clientID = ui->lineEditUserContextID->text().toInt();
        _ClientInfo *pClientInfo = m_Server.m_mapAllClients.value(clientID, nullptr);
        if(pClientInfo != nullptr)
        {
            //_ClientInfo* pClientInfo = clientMap.value(pClientInfo->m_SocketContext.pIOCPSocketContext);
            m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_OTHER_TYPE) << ui->lineEditPacket->text();
            bool bRet = m_Server.m_IOCPModel.send(pClientInfo);
            Info(tr("发送数据给用户%1(%2),返回%3").arg((int)pClientInfo->m_SocketContext.nSocketID).arg((int)pClientInfo->m_SocketContext.pIOCPSocketContext).arg(bRet));
            return;
        }
        else
        {
            Info(tr("没有%1").arg(clientID));
        }
    });

    //IOCP池调试
    connect(ui->pushButtonDebug,&QPushButton::clicked,this,[=](){
        m_Server.m_IOCPModel.Debug(ui->lineEditDebugValue->text().toInt());
    });

    //本地调试信息
    connect(ui->pushButtonDebugCount,&QPushButton::clicked,this,[=](){
        Info(tr("[DEBUG]Accepted(服务软件运行后总链接数):%1").arg(m_Server.m_nAcceptedCount));
        Info(tr("[DEBUG]GroupPoolInfo(群数):%1,%2").arg(m_Server.m_poolClientsGroupInfo.m_mapUsing.count()).arg(m_Server.m_poolClientsGroupInfo.m_listEmpty.count()));
        Info(tr("[DEBUG]GroupCount(群数):%1").arg(m_Server.m_mapGroups.count()));
    });

    //清零统计
    connect(ui->pushButtonZero,&QPushButton::clicked,this,[=](){
        m_Server.m_nAcceptedCount = 0;
    });

}

int GameServer::initOnce()
{
    //要在 信号/槽/属性 的参数中使用，或者qml中使用下列类型的函数或数据，则注册一下！字符串名不能随意更改!
    /*
     * 1.enum类型:
     *      如果信号槽的参数要使用Q_ENUMS或Q_FLAGS,需要注册一下!
     *      注册方法:如果有 类前缀,参数中不能使用 类前缀!!!比如只能:
     *          qRegisterMetaType<[类名::]enum名>("enum名");
     * 2.类 类型:
     *      QML中需要使用其类的函数,或信号槽的参数中需要使用其类型,则需要注册一下:
     *      注册方法:如果有 类前缀,参数中必须要有 类前缀!!!比如:
     *          qRegisterMetaType<[类名::]类名>("[类名::]类名");
    */
    qRegisterMetaType<QObjectList>("QObjectList");      //qml中使用其函数
    //qRegisterMetaType<_BaseObject::_ObjType>("_ObjType");  //信号/槽参数中使用
    //qRegisterMetaType<_BaseObject::_Flags>("_Flags");
    //qRegisterMetaType<GameCore::_GameButtonValue>("_GameButtonValue");
    qRegisterMetaType<GameModel::_GameStatus>("GameModel_GameStatus");
    qRegisterMetaType<_ClientGroupStatus>("_ClientGroupStatus");

    qRegisterMetaType<_SocketInfo::_SocketContext>("_SocketInfo::_SocketContext");
    qRegisterMetaType<_GameUserData>("_GameUserData");



//数据库
    m_pDatabase = new Database;
    //m_pGameLongTask = new GameLongTask;

    connect(m_pDatabase->m_pMysql,&Mysql::s_Critical,this,&GameServer::Critical);

    connect(m_pDatabase->m_pMysql,&Mysql::s_Debug,this,&GameServer::Debug);

    //!!!注意这里：把游戏服务器和信息服务器合并，以后人多了分开!!!
    connect(m_pDatabase, &Database::s_QueryUserFinished, this, [=](_SocketInfo::_SocketContext socketContext, int code, QString msg, QByteArray ba, _GameUserData gameUserData)
    {
        //qDebug() << socketContext.nSocketID << socketContext.pIOCPSocketContext;

        _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

        switch(code)
        {
        case 0:
            pGameUserData->m_unID = gameUserData.m_unID;
            pGameUserData->m_strUserName = gameUserData.m_strUserName;
            //pGameUserData->m_nServerID = 1;
            //pGameUserData->m_strNickName = gameUserData.m_strNickName;
            //pGameUserData->m_nSex = gameUserData.m_nSex;
            ////pGameUserData->m_unUserGameID = gameUserData.m_unUserGameID;

            //发送 游戏服务器 信息
            //code = m_DatabaseSwap.getGameServerInfoToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo));
            //sendUserPetsInfo(pClientInfo);

            Info(tr("[GameServer]%1 登录服务器成功：%2，%3").arg(pGameUserData->m_strUserName).arg(pGameUserData->m_unID).arg(pGameUserData->m_nVersion));

            break;
        case 1:
        case 2:
            Info(tr("[GameServer]%1 登录服务器失败:%2").arg(pGameUserData->m_strUserName).arg(code));
            break;
        default:
            Critical(tr("[!GameServer]服务器{登录}ERROR:%1(%2)").arg(code).arg(msg));
        }


        //如果已经不存在了
        if(pClientInfo->m_bDisconnected /* || !m_Server.m_IOCPModel.IsSocketExist(socketContext)*/)
            return;

        m_Server.m_IOCPModel.CorrectDataLength(ba);
        if(!m_Server.m_IOCPModel.send(pClientInfo->m_SocketContext, ba))
            ;


        if(0 == code)
        {
            //发送 游戏服务器 信息
            //code = m_DatabaseSwap.getGameServerInfoToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo));
            QMetaObject::invokeMethod(m_pDatabase,"sl_GetGameServerInfoToBuffer"
                                      ,Qt::AutoConnection
                                      //,Q_RETURN_ARG(QVariant, v)
                                      ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_CLIENT_TYPE))
                                      ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                      );


            /*
            //发送 游戏服务器 信息
            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_RESPONSE
                                                         << (qint16)INFO_SERVER_CLIENT;
                                                         << (qint16)INFO_SERVER_SERVERINFO;

            //ret = m_DatabaseSwap.getGameServerInfoToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo));
            switch(ret) {
            case 0:
                Debug(tr("[GameServer]获取ServerInfo"));
                break;
            default:
                {
                    Critical(tr("[!GameServer]服务器{获取ServerInfo}ERROR:%1").arg(ret));
                    m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_SERVERINFO_FAIL;
                }
            }
            */
        }

    });

    connect(m_pDatabase, &Database::s_RegisterUserFinished, this, [=](_SocketInfo::_SocketContext socketContext, int code, QString msg, QByteArray ba, _GameUserData gameUserData)
    {
        //qDebug() << socketContext.nSocketID << socketContext.pIOCPSocketContext;

        _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

        switch(code)
        {
        case 0:
            pGameUserData->m_unID = gameUserData.m_unID;
            pGameUserData->m_strUserName = gameUserData.m_strUserName;
            //pGameUserData->m_nServerID = 1;

            Info(tr("[GameServer]%1 注册服务器成功").arg(pGameUserData->m_strUserName));

            break;
        case 1:
            Info(tr("[GameServer]%1 注册服务器失败:%2").arg(pGameUserData->m_strUserName).arg(msg));
            break;
        default:
            Critical(tr("[!GameServer]服务器{注册}Error:%1(%2)").arg(code).arg(msg));
        }


        //如果已经不存在了
        if(pClientInfo->m_bDisconnected /* || !m_Server.m_IOCPModel.IsSocketExist(socketContext)*/)
            return;

        m_Server.m_IOCPModel.CorrectDataLength(ba);
        if(!m_Server.m_IOCPModel.send(pClientInfo->m_SocketContext, ba))
            ;


        if(0 == code)
        {
            //发送 游戏服务器 信息
            //code = m_DatabaseSwap.getGameServerInfoToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo));
            QMetaObject::invokeMethod(m_pDatabase,"sl_GetGameServerInfoToBuffer"
                                      ,Qt::AutoConnection
                                      //,Q_RETURN_ARG(QVariant, v)
                                      ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_CLIENT_TYPE))
                                      ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                      );
        }
    });

    connect(m_pDatabase, &Database::s_GetGameServerInfoToBufferFinished, this, [=](_SocketInfo::_SocketContext socketContext, int code, QString msg, QByteArray ba)
    {
        _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

        switch(code)
        {
        case 0:
            Debug(tr("[GameServer]获取ServerInfo"));
            break;
        default:
            Critical(tr("[!GameServer]服务器{获取ServerInfo}ERROR:%1(%2)").arg(code).arg(msg));
        }

        //如果已经不存在了
        if(pClientInfo->m_bDisconnected /* || !m_Server.m_IOCPModel.IsSocketExist(socketContext)*/)
            return;

        m_Server.m_IOCPModel.CorrectDataLength(ba);
        if(!m_Server.m_IOCPModel.send(pClientInfo->m_SocketContext, ba))
            ;

    });

    connect(m_pDatabase, &Database::s_GetGameUserInfoToBufferFinished, this, [=](_SocketInfo::_SocketContext socketContext, int code, QString msg, QByteArray ba, _GameUserData gud)
    {
        _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);


        /*_ClientInfo *pClientInfo1 = m_hashAllClientInfo.value(gud.m_unUserGameID, nullptr);
        if(nullptr != pClientInfo1)
        {
            code = 2;
            ba.clear();
            QDataStream ds(&ba,QIODevice::ReadWrite);
            ds.device()->seek(ba.size());
            ds << (qint16)GAME_SERVER_RESPONSE << (qint16)GAME_SERVER_CLIENT << (qint16)GAME_SERVER_CLIENT_GAMEUSERINFO
                  << (qint16)GAME_SERVER_CLIENT_GAMEUSERINFO_FAIL << (qint16)code;

        }*/


        switch(code)
        {
        case 0:
            {
                _ClientInfo *pClientInfo1 = m_hashAllClientInfo.value(gud.m_unUserGameID, nullptr);
                if(nullptr != pClientInfo1)
                {
                    ExitGroup(pClientInfo1, false, false);
                    DisconnectClient(pClientInfo1, 1);
                    //m_Server.m_IOCPModel.Close(pClientInfo1->m_SocketContext);
                    //m_hashAllClientInfo.remove(gud.m_unUserGameID, pClientInfo1);
                }

                m_hashAllClientInfo.insert(gud.m_unUserGameID, pClientInfo);


                //pGameUserData->m_unID = gud.m_unID;
                pGameUserData->m_unUserGameID = gud.m_unUserGameID;
                pGameUserData->m_strNickName = gud.m_strNickName;
                pGameUserData->m_nSex = gud.m_nSex;
                pGameUserData->m_nScore = gud.m_nScore;
                pGameUserData->m_vExtraData = gud.m_vExtraData;

                Info(tr("[GameServer]%1 登陆游戏服务器成功（%2，%3，%4，%5，%6，%7）")
                     .arg(pGameUserData->m_strUserName)
                     .arg(pGameUserData->m_unID)
                     .arg(pGameUserData->m_unUserGameID)
                     .arg(pGameUserData->m_strNickName)
                     .arg(pClientInfo->m_SocketContext.nSocketID)
                     .arg(pClientInfo->m_nClientType)
                     .arg(pGameUserData->m_nVersion)
                     );
            }
            break;
        case 1:
            Info(tr("[GameServer]%1 需要注册GameUserInfo（%2）")
                 .arg(pGameUserData->m_strUserName)
                 .arg(pGameUserData->m_unID)
                 );
            break;
        default:
            Critical(tr("[!GameServer]服务器{获取GameUserInfo}ERROR:%1(%2)").arg(code).arg(msg));
        }


        //如果已经不存在了
        if(pClientInfo->m_bDisconnected /* || !m_Server.m_IOCPModel.IsSocketExist(socketContext)*/)
            return;

        m_Server.m_IOCPModel.CorrectDataLength(ba);
        if(!m_Server.m_IOCPModel.send(pClientInfo->m_SocketContext, ba))
            ;

    });


    connect(m_pDatabase, &Database::s_RegisterGameUserFinished, this, [=](_SocketInfo::_SocketContext socketContext, int code, QString msg, QByteArray ba, _GameUserData gud)
    {
        _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);


        /*_ClientInfo *pClientInfo1 = m_hashAllClientInfo.value(gud.m_unUserGameID, nullptr);
        if(nullptr != pClientInfo1)
        {
            code = 2;
            ba.clear();
            QDataStream ds(&ba,QIODevice::ReadWrite);
            ds.device()->seek(ba.size());
            ds << (qint16)GAME_SERVER_RESPONSE << (qint16)GAME_SERVER_CLIENT << (qint16)GAME_SERVER_CLIENT_GAMEUSERINFO
                  << (qint16)GAME_SERVER_CLIENT_GAMEUSERINFO_FAIL << (qint16)code;

        }*/

        switch(code)
        {
        case 0:
            {
                _ClientInfo *pClientInfo1 = m_hashAllClientInfo.value(gud.m_unUserGameID, nullptr);
                if(nullptr != pClientInfo1)
                {
                    ExitGroup(pClientInfo1, false, false);
                    DisconnectClient(pClientInfo1, 1);
                    //m_Server.m_IOCPModel.Close(pClientInfo1->m_SocketContext);
                    //m_hashAllClientInfo.remove(gud.m_unUserGameID, pClientInfo1);
                }

                m_hashAllClientInfo.insert(gud.m_unUserGameID, pClientInfo);


                //pGameUserData->m_unID = gud.m_unID;
                pGameUserData->m_unUserGameID = gud.m_unUserGameID;
                //pGameUserData->m_strNickName = gud.m_strNickName;
                pGameUserData->m_nSex = gud.m_nSex;

                Info(tr("[GameServer]%1 游戏服务器注册成功（%2，%3，%4，%5，%6，%7）")
                     .arg(pGameUserData->m_strUserName)
                     .arg(pGameUserData->m_unID)
                     .arg(pGameUserData->m_unUserGameID)
                     .arg(pGameUserData->m_strNickName)
                     .arg(pClientInfo->m_SocketContext.nSocketID)
                     .arg(pClientInfo->m_nClientType)
                     .arg(pGameUserData->m_nVersion)
                     );
            }
            break;
        case 1:
            Info(tr("[GameServer]%1(%2) 游戏服务器注册错误：%3")
                 .arg(pGameUserData->m_strUserName)
                 .arg(pGameUserData->m_strNickName)
                 .arg(msg)
                 );

            pGameUserData->m_strNickName = "";
            pGameUserData->m_nSex = -1;
            break;
        default:
            Critical(tr("[!GameServer]服务器{RegGameUserInfo}ERROR:%1(%2)").arg(code).arg(msg));

            pGameUserData->m_strNickName = "";
            pGameUserData->m_nSex = -1;
        }


        //如果已经不存在了
        if(pClientInfo->m_bDisconnected /* || !m_Server.m_IOCPModel.IsSocketExist(socketContext)*/)
            return;

        m_Server.m_IOCPModel.CorrectDataLength(ba);
        if(!m_Server.m_IOCPModel.send(pClientInfo->m_SocketContext, ba))
            ;

    });


    connect(m_pDatabase, &Database::s_SetClientShareExtraGameData, this, [=](_SocketInfo::_SocketContext socketContext, int code, QString msg, QByteArray ba)
    {
        //qDebug() << socketContext.nSocketID << socketContext.pIOCPSocketContext;

        _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

        switch(code)
        {
        case 0:
            Debug(tr("[GameServer]SetClientShareExtraGameData"));
            break;
        default:
            Critical(tr("[!GameServer]服务器{SetClientShareExtraGameData}ERROR:%1(%2)").arg(code).arg(msg));
        }

        //如果已经不存在了
        if(pClientInfo->m_bDisconnected /* || !m_Server.m_IOCPModel.IsSocketExist(socketContext)*/)
            return;

        m_Server.m_IOCPModel.CorrectDataLength(ba);
        if(!m_Server.m_IOCPModel.send(pClientInfo->m_SocketContext, ba))
            ;

    });


    connect(m_pDatabase, &Database::s_GetClientGameData, this, [=](_SocketInfo::_SocketContext socketContext, int code, QString msg, QByteArray ba)
    {
        //qDebug() << socketContext.nSocketID << socketContext.pIOCPSocketContext;

        _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

        if(code >= 0)
            Debug(tr("[GameServer]GetData:%1").arg(code));
        else
            Critical(tr("[!GameServer]服务器{GetData}ERROR:%1(%2)").arg(code).arg(msg));

        //如果已经不存在了
        if(pClientInfo->m_bDisconnected /* || !m_Server.m_IOCPModel.IsSocketExist(socketContext)*/)
            return;

        m_Server.m_IOCPModel.CorrectDataLength(ba);
        if(!m_Server.m_IOCPModel.send(pClientInfo->m_SocketContext, ba))
            ;

    });

    connect(m_pDatabase, &Database::s_SetClientGameData, this, [=](_SocketInfo::_SocketContext socketContext, int code, QString msg, QByteArray ba)
    {
        //qDebug() << socketContext.nSocketID << socketContext.pIOCPSocketContext;

        _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

        switch(code)
        {
        case 0:
            Debug(tr("[GameServer]SetData(No Update)"));
            break;
        case 1:
            Debug(tr("[GameServer]SetData(Insert)"));
            break;
        case 2:
            Debug(tr("[GameServer]SetData(Update)"));
            break;
        default:
            Critical(tr("[!GameServer]服务器{SetData}ERROR:%1(%2)").arg(code).arg(msg));
        }

        //如果已经不存在了
        if(pClientInfo->m_bDisconnected /* || !m_Server.m_IOCPModel.IsSocketExist(socketContext)*/)
            return;

        m_Server.m_IOCPModel.CorrectDataLength(ba);
        if(!m_Server.m_IOCPModel.send(pClientInfo->m_SocketContext, ba))
            ;

    });

    connect(m_pDatabase, &Database::s_DeleteClientGameData, this, [=](_SocketInfo::_SocketContext socketContext, int code, QString msg, QByteArray ba)
    {
        //qDebug() << socketContext.nSocketID << socketContext.pIOCPSocketContext;

        _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

        switch(code)
        {
        case 0:
            Debug(tr("[GameServer]DeleteData"));
            break;
        default:
            Critical(tr("[!GameServer]服务器{DeleteData}ERROR:%1(%2)").arg(code).arg(msg));
        }

        //如果已经不存在了
        if(pClientInfo->m_bDisconnected /* || !m_Server.m_IOCPModel.IsSocketExist(socketContext)*/)
            return;

        m_Server.m_IOCPModel.CorrectDataLength(ba);
        if(!m_Server.m_IOCPModel.send(pClientInfo->m_SocketContext, ba))
            ;

    });

    connect(m_pDatabase, &Database::s_InsertClientData, this, [=](_SocketInfo::_SocketContext socketContext, int code, QString msg, QByteArray ba)
    {
        //qDebug() << socketContext.nSocketID << socketContext.pIOCPSocketContext;

        _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

        switch(code)
        {
        case 0:
            Debug(tr("[GameServer]InsertData"));
            break;
        default:
            Critical(tr("[!GameServer]服务器{InsertData}ERROR:%1(%2)").arg(code).arg(msg));
        }

        //如果已经不存在了
        if(pClientInfo->m_bDisconnected /* || !m_Server.m_IOCPModel.IsSocketExist(socketContext)*/)
            return;

        m_Server.m_IOCPModel.CorrectDataLength(ba);
        if(!m_Server.m_IOCPModel.send(pClientInfo->m_SocketContext, ba))
            ;

    });

    connect(m_pDatabase, &Database::s_UpdateClientData, this, [=](_SocketInfo::_SocketContext socketContext, int code, QString msg, QByteArray ba)
    {
        //qDebug() << socketContext.nSocketID << socketContext.pIOCPSocketContext;

        _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);
        
        switch(code)
        {
        case 0:
            Debug(tr("[GameServer]UpdateData"));
            break;
        default:
            Critical(tr("[!GameServer]服务器{UpdateData}ERROR:%1(%2)").arg(code).arg(msg));
        }

        //如果已经不存在了
        if(pClientInfo->m_bDisconnected /* || !m_Server.m_IOCPModel.IsSocketExist(socketContext)*/)
            return;

        m_Server.m_IOCPModel.CorrectDataLength(ba);
        if(!m_Server.m_IOCPModel.send(pClientInfo->m_SocketContext, ba))
            ;

    });


    connect(m_pDatabase, &Database::s_DBQuery, this, [=](_SocketInfo::_SocketContext socketContext, int code, QString msg, QByteArray ba)
    {
        //qDebug() << socketContext.nSocketID << socketContext.pIOCPSocketContext;

        _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

        switch(code)
        {
        case 0:
            Debug(tr("[GameServer]s_DBQuery"));
            break;
        default:
            Critical(tr("[!GameServer]服务器{DBQuery}ERROR:%1(%2)").arg(code).arg(msg));
        }

        //如果已经不存在了
        if(pClientInfo->m_bDisconnected /* || !m_Server.m_IOCPModel.IsSocketExist(socketContext)*/)
            return;

        m_Server.m_IOCPModel.CorrectDataLength(ba);
        if(!m_Server.m_IOCPModel.send(pClientInfo->m_SocketContext, ba))
            ;

    });



    connect(m_pDatabase, &Database::s_Critical, this, [=](int code, QString msg)
    {
        Critical(tr("[!GameServer]服务器{Database}ERROR:%1(%2)").arg(code).arg(msg));
    });




    m_pDatabase->m_pMysql->getMySqlInfo()["HostName"] = m_Server.m_vmapConfig["HostName"].toString();
    m_pDatabase->m_pMysql->getMySqlInfo()["DatabaseName"] = m_Server.m_vmapConfig["DatabaseName"].toString();
    m_pDatabase->m_pMysql->getMySqlInfo()["UserName"] = m_Server.m_vmapConfig["UserName"].toString();
    m_pDatabase->m_pMysql->getMySqlInfo()["Password"] = m_Server.m_vmapConfig["Password"].toString();



    m_Server.m_nRecievedDataMaxSize = 1024 * 1024;   //1024K
    m_Server.m_poolClientsGroupInfo.m_nReserveCount = 1;

    m_Server.m_fnJoinGroupCallBack = fnJoinGroupCallBack;
    m_Server.m_pJoinGroupCallBackParam = this;

    m_Server.m_IOCPModel.SetServerIP("0.0.0.0");
    m_Server.m_IOCPModel.SetWatchThreadInterval(100000);
    m_Server.m_IOCPModel.SetIOCPFlag(IOCP_Pleafles::IOCPFlag_SendHeartPacket);
    m_Server.m_IOCPModel.SetHeartData("H",1);
    m_Server.m_IOCPModel.m_baPackageHeaderFlag.setRawData("LMS",3);
    m_Server.m_IOCPModel.SetIOCPCountProperty(0,-1,SOMAXCONN,10,10);

    m_Server.m_IOCPModel.SetIOCPStopCallback((void*)fnStopCallBack, this);

    m_Server.m_IOCPModel.SetIOCPSetSocketExtraDataCallback((void*)Fn_IOCP_SetSocketExtraData_Callback);
    m_Server.m_IOCPModel.SetIOCPUnsetSocketExtraDataCallback((void*)Fn_IOCP_UnsetSocketExtraData_Callback);
    m_Server.m_IOCPModel.SetIOCPInitSocketExtraDataCallback((void*)Fn_IOCP_Init_SocketExtraData_Callback);
    m_Server.m_IOCPModel.SetIOCPReleaseSocketExtraDataCallback((void*)Fn_IOCP_Release_SocketExtraData_Callback);


    connect(&m_Server,&Server::s_Info,this,&GameServer::Info);//,Qt::QueuedConnection);
    connect(&m_Server,&Server::s_Debug,this,&GameServer::Debug);//,Qt::QueuedConnection);
    connect(&m_Server,&Server::s_Warning,this,&GameServer::Warning);//,Qt::QueuedConnection);
    connect(&m_Server,&Server::s_Critical,this,&GameServer::Critical);//,Qt::QueuedConnection);
    //connect(&m_Server,&Server::s_ReadyRead,this,&Server::onReadyRead,Qt::DirectConnection);
    connect(&m_Server,&Server::s_ReadyRead,this,&GameServer::onReadyRead,Qt::QueuedConnection);
    connect(&m_Server,&Server::s_Accept,this,&GameServer::onAccept,Qt::QueuedConnection);
    connect(&m_Server,&Server::s_Disconnect,this,&GameServer::onDisconnect,Qt::QueuedConnection);



    //UDP
    m_pUDPIOCPModel = new UDPIOCP_Pleafles;
    m_pUDPIOCPModel->create();

    m_pUDPIOCPModel->SetIOCPMessageCallback((void*)UDPIOCP_Pleafles::Fn_IOCP_Message_Callback,m_pUDPIOCPModel);
    m_pUDPIOCPModel->SetIOCPRecvFromCallback((void*)UDPIOCP_Pleafles::Fn_IOCP_RecvFrom_Callback,m_pUDPIOCPModel);
    m_pUDPIOCPModel->SetIOCPSendToCallback((void*)UDPIOCP_Pleafles::Fn_IOCP_SendTo_Callback,m_pUDPIOCPModel);
    m_pUDPIOCPModel->SetIOCPStopCallback((void*)fnStopCallBack_UDP, this);

    connect(m_pUDPIOCPModel,&UDPIOCP_Pleafles::s_Info,this,&GameServer::Info);//,Qt::QueuedConnection);
    connect(m_pUDPIOCPModel,&UDPIOCP_Pleafles::s_Debug,this,&GameServer::Debug);//,Qt::QueuedConnection);
    connect(m_pUDPIOCPModel,&UDPIOCP_Pleafles::s_Warning,this,&GameServer::Warning);//,Qt::QueuedConnection);
    connect(m_pUDPIOCPModel,&UDPIOCP_Pleafles::s_Critical,this,&GameServer::Critical);//,Qt::QueuedConnection);
    //connect(m_pUDPIOCPModel,&UDPIOCP_Pleafles::s_ReadyRead,this,&Server::onReadyRead,Qt::DirectConnection);
    connect(m_pUDPIOCPModel,&UDPIOCP_Pleafles::s_ReadyRead,this,&GameServer::onUDPReadyRead,Qt::QueuedConnection);

    m_pUDPIOCPModel->InitOnce();
    m_pUDPIOCPModel->SetServerIP("0.0.0.0");
    m_pUDPIOCPModel->SetIOCPCountProperty(0, 10);
    m_pUDPIOCPModel->SetWatchThreadInterval(300000);



    //设置四种回调函数
    if(_ClientsGroupInfo::SetGroupExtraDataCallback == nullptr)
        _ClientsGroupInfo::SetGroupExtraDataCallback = Fn_SetGroupExtraData_Callback;
    if(_ClientsGroupInfo::UnsetGroupExtraDataCallback == nullptr)
        _ClientsGroupInfo::UnsetGroupExtraDataCallback = Fn_UnsetGroupExtraData_Callback;
    _ClientsGroupInfo::InitGroupExtraDataCallback = Fn_InitGroupExtraData_Callback;
    _ClientsGroupInfo::ReleaseGroupExtraDataCallback = Fn_ReleaseGroupExtraData_Callback;



    lmsSrand(-1);
    lms_DefaultRandom(0, 1, -1);



    m_ServerType = (_ServerType)m_Server.m_vmapConfig["ServerType"].toInt();
    m_nRecordUserOnlineLog = m_Server.m_vmapConfig["RecordUserOnlineLog"].toInt();



    ui->lineEditPort->setText(m_Server.m_vmapConfig["ListenPort"].toString());
    if(m_Server.m_vmapConfig.value("AutoStart",0) != 0)
        emit ui->pushButtonStart->clicked();



    //!server.listen(QHostAddress::Any,723);
/*
    Debug("");

    //查询所有数据
    QString strSQL = "select * from leamus_ylant_io";
    QSqlQuery sqlQuery(db);
    //sql_query.prepare(strSQL);  //有错误1/2：使用这个且
    if(!sqlQuery.exec(strSQL)) //有错误2/2：忽略参数
    {
        qDebug()<<"!"<<sqlQuery.lastError();
    }
    else
    {
        while(sqlQuery.next())
        {
            int id = sqlQuery.value(0).toInt();
            QString templ_name = sqlQuery.value(1).toString();
            qDebug()<<QString("Id:%1;Templ Name:%2").arg(id).arg(templ_name);
        }
    }
*/
    //emit ui->pushButtonStart->clicked();


    qDebug() << "[GameServer]GameServer in threadID:" << QThread::currentThreadId();
    return 0;
}

GameServer::~GameServer()
{
    delete ui;
}



bool GameServer::Start()
{
    if(m_pDatabase->m_pMysql->connectDB())
        Info(tr("[GameServer]连接数据库服务器成功"));
    else
    {
        Critical(tr("[!GameServer]连接数据库服务器失败!"));
        return false;
    }

    m_Server.m_IOCPModel.SetServerPort(ui->lineEditPort->text().toInt());
    if(m_Server.Start() == false)
    {
        m_pDatabase->m_pMysql->close();
        Critical(tr("[!GameServer]服务器启动失败!"));
        return false;
    }

    m_pUDPIOCPModel->SetServerPort(ui->lineEditPortUDP->text().toInt());
    if(m_pUDPIOCPModel->Start() == false)
    {
        m_Server.Stop();
        m_pDatabase->m_pMysql->close();
        Critical("[!GameServer]UDPIOCP服务器启动失败!");
        return false;
    }

    //加入0房间,表示不能有全0房间
    m_hashNumberGroups.insert(0, QUuid());      //QUuid::createUuid()

    Info(tr("[GameServer]服务器启动完毕"));

    return true;
}

void GameServer::Stop()
{
    m_pUDPIOCPModel->Stop();
    m_Server.Stop();
    //m_pDatabase->m_pMysql->close();

    Info(tr("[GameServer]服务器正在停止"));
}

void GameServer::__Exit()
{
    //m_DatabaseSwap.close();


    //等待所有事件处理完毕
    //Wait(5000);
    ////QEventLoop eventloop;
    ////QTimer::singleShot(msec, &eventloop, SLOT(quit()));
    ////eventloop.exec(flags);


    delete m_pUDPIOCPModel;
    m_pDatabase->destroy();
    m_pDatabase->thread()->wait();
    //m_pGameLongTask->destroy();

    qApp->exit(0);
}

void GameServer::__StopCallback()
{
    m_pDatabase->m_pMysql->close();
    m_hashNumberGroups.clear();
    m_Server.__StopCallback();

    Info(tr("[GameServer]TCP_IOCP服务器停止完毕"));
}

void GameServer::__StopCallback_UDP()
{
    m_pUDPIOCPModel->StopCallback();

    Info(tr("[GameServer]UDP_IOCP服务器停止完毕"));
}



qint32 GameServer::CreateGroup(_ClientInfo *pClientInfo, qint32 playerMaxCount, qint32 playerWatchingMaxCount, QString password, qint32 groupID, qint32 type, QVariant vData)
{
    int ret = -999;
    m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_RESPONSE
                                               << (qint16)GAME_SERVER_GROUP
                                               << (qint16)GAME_SERVER_GROUP_CREATE;

    if(pClientInfo->m_pGroup != nullptr)
    {
        ret = -1;
        m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_GROUP_CREATE_FAIL
                                                   << (qint16)ret;
        m_Server.m_IOCPModel.send(pClientInfo);

        Warning(tr("[!GameServer]用户已经进入了一个房间!"));

        return ret;
    }

    if(groupID < 0)
    {
        ret = -2;
        m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_GROUP_CREATE_FAIL
                                                   << (qint16)ret;
        m_Server.m_IOCPModel.send(pClientInfo);

        Critical(tr("[!GameServer]创建房间号出错:%1!").arg(groupID));

        return ret;
    }

    if(m_hashNumberGroups.contains(groupID))
    {
        ret = -3;
        m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_GROUP_CREATE_FAIL
                                                   << (qint16)ret;
        m_Server.m_IOCPModel.send(pClientInfo);

        Critical(tr("[!GameServer]创建房间已存在:%1!").arg(groupID));

        return ret;
    }

    _ClientsGroupInfo *pGroup = m_Server.CreateGroup(playerMaxCount, playerWatchingMaxCount, password);
    if(pGroup == nullptr)
    {
        ret = -4;
        m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_GROUP_CREATE_FAIL
                                                   << (qint16)ret;
        m_Server.m_IOCPModel.send(pClientInfo);

        Critical(tr("[!GameServer]创建房间失败:%1!").arg(ret));

        return ret;
    }
    else
    {
        _GameGroup *pGameGroup = (_GameGroup*)pGroup->m_pClientsGroupExtraData;

        pGameGroup->m_nType = type;
        pGameGroup->m_vData = vData;
        pGameGroup->m_nGroupID = groupID;

        m_hashNumberGroups.insert(groupID,pGroup->m_uuid);

        m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                << (qint16)GAME_SERVER_GROUP_CREATE_SUCCESS
                << groupID;
        m_Server.m_IOCPModel.send(pClientInfo);
        m_Server.sendGroupInfoToAllClients(pGroup);

        Info(tr("[GameServer]创建房间成功:%1(%2),%3,%4").arg(groupID).arg(pGroup->m_uuid.toString()).arg(playerMaxCount).arg(type));

        return groupID;
    }
}


/*/客户状态不对-5;正常返回 m_Server.JoinGroup
int JoinGroup(_ClientInfo* pClientInfo, _ClientsGroupInfo *pGroup, const QString& password = "")
{
    _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

    if(pClientInfo->m_ClientGroupStatus != _ClientGroupStatus::GroupStatus_Nothing)
    {
        return -5;
    }
    else
    {
        int ret = m_Server.JoinGroup(pClientInfo, pGroup, password);
        if(ret >= 0)
        {
            //随机改变群主
            if(pGroup->m_pGroupMaster == nullptr)
                pGroup->ChangeGroupMaster(-1);

            pClientInfo->m_ClientGroupStatus = _ClientGroupStatus::GroupStatus_Waiting;
        }
        else
        {

        }
        return ret;
    }
}
*/


int GameServer::JoinGroup(_ClientInfo* pClientInfo, qint32 groupID, const QString& password, qint32 joinType)
{
    int ret = -999;

    m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
            << (qint16)GAME_SERVER_RESPONSE
            << (qint16)GAME_SERVER_GROUP
            << (qint16)GAME_SERVER_GROUP_JOINGROUP;

    _ClientsGroupInfo *pGroup = nullptr;
    QUuid uuid;
    //随机找房间
    if(groupID == 0)
    {
        pGroup = m_Server.SearchGroup(pClientInfo, password);
        if(pGroup == nullptr)
        {
            ret = -11;
            m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                    << (qint16)GAME_SERVER_GROUP_JOINGROUP_FAIL
                    << (qint16)ret;
            m_Server.m_IOCPModel.send(pClientInfo);

            Debug(tr("[GameServer]房间都满:%1!").arg(ret));
            return ret;
        }
        uuid = pGroup->m_uuid;
    }
    else
    {
        if(groupID < 0 || !m_hashNumberGroups.contains(groupID))
        {
            ret = -12;
            m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                    << (qint16)GAME_SERVER_GROUP_JOINGROUP_FAIL
                    << (qint16)ret;
            m_Server.m_IOCPModel.send(pClientInfo);

            Debug(tr("[GameServer]房间找不到:%1!").arg(ret));
            return ret;
        }
        uuid = m_hashNumberGroups.value(groupID);
        pGroup = m_Server.GetGroup(uuid);
    }


    _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

    if(pClientInfo->m_ClientGroupStatus != _ClientGroupStatus::GroupStatus_Nothing)
    {
        qint32 groupID = 0;
        QString groupUuid;
        if(pClientInfo->m_pGroup != nullptr)
        {
            groupID = ((_GameGroup*)pClientInfo->m_pGroup->m_pClientsGroupExtraData)->m_nGroupID;
            groupUuid = pClientInfo->m_pGroup->m_uuid.toString();
        }

        ret = -13;
        m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                << (qint16)GAME_SERVER_GROUP_JOINGROUP_FAIL
                << (qint16)ret;
        m_Server.m_IOCPModel.send(pClientInfo);

        Critical(tr("[!GameServer]客户状态不正确:%1,%2(%3),%4(%5)")
                 .arg(pGameUserData->m_strNickName)
                 .arg(groupID)
                 .arg(groupUuid)
                 .arg(ret)
                 .arg(pClientInfo->m_ClientGroupStatus));

        return ret;
    }
    else
    {
        ret = m_Server.JoinGroup(pClientInfo, uuid, password, joinType);
        if(ret >= 0)
        {
            qint32 count = pGroup->m_mapAllClients.count();
            //_ClientsGroupInfo *pGroup = m_hashNumberGroups.value(groupID, nullptr);

            //获得真实groupID(因为有可能是随机加入房间,groupID为0)
            groupID = ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->m_nGroupID;

            m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                    << (qint16)GAME_SERVER_GROUP_JOINGROUP_SUCCESS
                    << groupID
                    << password
                    << pGroup->m_GroupInfo.nClientsMaxCount
                    << pClientInfo->m_nIndex
                    << ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->isRunning()
                    << ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->m_vData
                       ;


            //给新客户 发送 群内所有客户信息（包括自己）
            m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                    << (qint32)count;

            _GameUserData *pGUD = nullptr;

            QMap<qint32, _ClientInfo*>::const_iterator ii;
            for(ii = pGroup->m_mapAllClients.constBegin(); ii != pGroup->m_mapAllClients.constEnd(); ++ii)
            {
                pGUD = ((_GameUserData*)((*ii)->m_pClientExtraData));

                m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                        << (*ii)->m_SocketContext.nSocketID
                        << (*ii)->m_nIndex
                        << pGUD->m_unUserGameID
                        << (pGroup->m_pGroupMaster == (*ii))
                        << (qint16)((*ii)->m_ClientGroupStatus)
                        << pGUD->m_strNickName
                        << pGUD->m_nSex
                        << pGUD->m_nScore
                        << pGUD->m_nServerID
                        << pGUD->m_vExtraData
                           ;
            }

            m_Server.m_IOCPModel.send(pClientInfo);



            //给群里其他客户发送 新客户信息
            QByteArray ba = pClientInfo->m_pGroup->m_pIOCP->newSendData(TRANSMIT_GROUP_TYPE);
            QDataStream ds(&ba,QIODevice::ReadWrite);
            ds.device()->seek(ba.size());
            ds << (qint16)GAME_SERVER_RESPONSE
               << (qint16)GAME_SERVER_GROUP
               << (qint16)GAME_SERVER_GROUP_OTHERSINFO
               << (qint16)GAME_SERVER_GROUP_OTHERSINFO_JOINGROUP
               << pClientInfo->m_SocketContext.nSocketID
               << pClientInfo->m_nIndex
               << pGameUserData->m_unUserGameID
               << ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->isRunning()
               << ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->m_bResetFrameWhenClientExitGroup
               << (bool)true    //加入

               << (pGroup->m_pGroupMaster == pClientInfo)
               << pGameUserData->m_strNickName
               << pGameUserData->m_nSex
               << pGameUserData->m_nScore
               << pGameUserData->m_nServerID
               << pGameUserData->m_vExtraData
                  ;
            pClientInfo->m_pGroup->m_pIOCP->CorrectDataLength(ba);
            pClientInfo->m_pGroup->SendToGroupAllClients(ba, pClientInfo, -1);


            m_Server.sendClientJoinInfoToAllClients(pClientInfo);


            if(joinType == 0)
                pClientInfo->ChangeGroupStatus(_ClientGroupStatus::GroupStatus_Waiting);
            else if(joinType == 1)
                pClientInfo->ChangeGroupStatus(_ClientGroupStatus::GroupStatus_ReadyToWatch);
            else
            {
                pClientInfo->ChangeGroupStatus(_ClientGroupStatus::GroupStatus_ReadyToWatch);
                Warning(tr("[!GameServer]JoinGroup客户改变状态错误:%1").arg(joinType));
            }


            Info(tr("[GameServer]客户加入房间:%1,%2(%3)").arg(pGameUserData->m_strNickName).arg(groupID).arg(pGroup->m_uuid.toString()));


            //随机改变群主
            if(pGroup->m_pGroupMaster == nullptr)
                SetGroupMaster(-1, pGroup, true);
                //pGroup->ChangeGroupMaster(-1);


            //如果房间正在玩状态,那么发送给客户 开始游戏
            if(pGroup->m_flagStatus & _ClientsGroupInfo::Status_Playing)
            {
                m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GAME_TYPE)
                        << (qint16)GAME_DATA
                        << (qint16)GAME_DATA_STARTGAME
                        << (qint16)GAME_DATA_STARTGAME_SUCCESS
                        << (bool)true
                           ;
                m_Server.m_IOCPModel.send(pClientInfo);
            }


            return ret;
        }
        else
        {
            //ret = -4;
            m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                    << (qint16)GAME_SERVER_GROUP_JOINGROUP_FAIL
                    << (qint16)ret;
            m_Server.m_IOCPModel.send(pClientInfo);

            switch(ret)
            {
            case -1:
                Critical(tr("[!GameServer]pClientInfo为空!"));
                break;
            case -2:
                Warning(tr("[!GameServer]客户已经加入房间!"));
                break;
            case -3:
                Critical(tr("[!GameServer]房间ID错误!"));
                break;
            case -4:
                Warning(tr("[!GameServer]查找房间失败!"));
                break;
            case -5:
                Debug(tr("[GameServer]房间被锁!"));
                break;
            case -6:
                Debug(tr("[GameServer]房间满!"));
                break;
            case -7:
                Debug(tr("[GameServer]密码错误!"));
                break;
            default:
                Critical(tr("[!GameServer]房间加入失败:%1").arg(ret));
            }

            return ret;
        }
    }
}


int GameServer::ExitGroup(_ClientInfo *pClientInfo, bool bKeepGroupIndex, bool groupWillClose)
{
    if(nullptr == pClientInfo)
        return -11;
    if(nullptr == pClientInfo->m_pGroup)
        return -12;

    _ClientsGroupInfo *pGroup = pClientInfo->m_pGroup;
    _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);
    bool bChangeMaster = (pGroup->m_pGroupMaster == pClientInfo);

    switch(pClientInfo->m_ClientGroupStatus)
    {
    case _ClientGroupStatus::GroupStatus_Playing:
    case _ClientGroupStatus::GroupStatus_ReJoining:
        break;
    case _ClientGroupStatus::GroupStatus_Waiting:
    case _ClientGroupStatus::GroupStatus_Readying:
    case _ClientGroupStatus::GroupStatus_ReadyToWatch:
    case _ClientGroupStatus::GroupStatus_Watching:
        bKeepGroupIndex = false;
        break;
    default:
        //Warning(tr("[!GameServer]客户退出状态WARNING:%1").arg(pClientInfo->m_ClientGroupStatus));
        //return -5;
        break;
    }


    m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
            << (qint16)GAME_SERVER_RESPONSE
            << (qint16)GAME_SERVER_GROUP
            << (qint16)GAME_SERVER_GROUP_EXITGROUP
               ;
    qint32 tmpIndex = pClientInfo->m_nIndex;

    int ret = m_Server.ExitGroup(pClientInfo, bKeepGroupIndex, pGameUserData->m_unUserGameID);


    //退群成功
    if(ret >= 0)
    {
        Info(tr("[GameServer]客户退出房间:%1,%2(%3)").arg(pGameUserData->m_strNickName).arg(((_GameGroup*)pGroup->m_pClientsGroupExtraData)->m_nGroupID).arg(pGroup->m_uuid.toString()));

        pClientInfo->ChangeGroupStatus(_ClientGroupStatus::GroupStatus_Nothing);
        if(pClientInfo->m_bDisconnected == false)
        {
            //发送成功
            m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                    << (qint16)GAME_SERVER_GROUP_EXITGROUP_SUCCESS;
            m_Server.m_IOCPModel.send(pClientInfo);
        }

        //Debug(tr("[GameServer]客户%1离开房间:%2").arg((int)pClientInfo).arg(pGroup->m_uuid.toString()));


        //如果群要关闭,则不给群里的其他客户发送退群消息
        if(groupWillClose == false)
        {
            //群里无人
            if(ret == 0)
            {
                if(pGroup->m_flagStatus & _ClientsGroupInfo::Status_AutoClose)
                {
                    QUuid uuidGroup = pGroup->m_uuid;
                    if(CloseGroup(pGroup) == 0) //关闭群
                    {
                        m_Server.sendGroupInfoToAllClients(uuidGroup,1);
                    }
                }
            }
            else    //如果房间内还有人,则发送
            {
                //给群内其他客户发送
                QByteArray ba = pGroup->m_pIOCP->newSendData(TRANSMIT_GROUP_TYPE);
                QDataStream ds(&ba,QIODevice::ReadWrite);
                ds.device()->seek(ba.size());
                ds << (qint16)GAME_SERVER_RESPONSE
                   << (qint16)GAME_SERVER_GROUP
                   << (qint16)GAME_SERVER_GROUP_OTHERSINFO
                   << (qint16)GAME_SERVER_GROUP_OTHERSINFO_JOINGROUP
                   << pClientInfo->m_SocketContext.nSocketID
                   << tmpIndex
                   << pGameUserData->m_unUserGameID
                   << ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->isRunning()
                   << ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->m_bResetFrameWhenClientExitGroup
                   << (bool)false       //退出

                   << (bool)bKeepGroupIndex  //是否保持Index
                      ;
                pGroup->m_pIOCP->CorrectDataLength(ba);
                pGroup->SendToGroupAllClients(ba, pClientInfo, -1);


                //如果游戏在运行
                if(pGroup->m_flagStatus & _ClientsGroupInfo::Status_Playing)
                {
                    if(!bKeepGroupIndex)
                    {
                        if(pClientInfo->m_ClientGroupStatus == GroupStatus_Playing || pClientInfo->m_ClientGroupStatus == GroupStatus_ReJoining)
                            ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->ClientExitRunningGroup(tmpIndex, pGameUserData->m_unUserGameID);
                    }
                }


                if(bChangeMaster)
                    SetGroupMaster(-1, pGroup, true);
            }
        }

        //给群外客户发送
        m_Server.sendClientJoinInfoToAllClients(pClientInfo);
    }
    else
    {
        if(pClientInfo->m_bDisconnected == false)
        {
            m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                    << (qint16)GAME_SERVER_GROUP_EXITGROUP_FAIL
                    << (qint16)ret;
            m_Server.m_IOCPModel.send(pClientInfo);
        }

        Critical(tr("[!GameServer]客户离开房间失败:%1").arg(ret));
    }
    return ret;
}


int GameServer::CloseGroup(_ClientsGroupInfo *pClientsGroupInfo, _ClientInfo *pClientInfo)
{
    qint32 groupID = -1;
    if(pClientsGroupInfo != nullptr)
    {
        //如果房间内还有人,则结束游戏并发送
        if(pClientsGroupInfo->m_flagStatus & _ClientsGroupInfo::Status_Playing)
        {
            ((_GameGroup*)pClientsGroupInfo->m_pClientsGroupExtraData)->sl_OverGame(GameModel::Game_Status_Terminated, -1);
            //((_GameGroup*)pClientsGroupInfo->m_pClientsGroupExtraData)->TerminateGame(GameModel::Game_Status_Terminated, -1);
        }


        //释放房间ExtraData
        groupID = ((_GameGroup*)pClientsGroupInfo->m_pClientsGroupExtraData)->m_nGroupID;
        if(groupID > 0)
        {
            m_hashNumberGroups.remove(groupID);
            //Info(tr("[GameServer]主动关闭房间:%1(%2)").arg(groupID).arg(pClientsGroupInfo->m_uuid.toString()));
        }
        else
        {
            Warning(tr("[!GameServer]WARNING!找不到房间:%1").arg(groupID));
        }

        /*/每人退群
        //ExitGroup会操作mapAllClients,导致迭代错误!!!
        QMap<qint32, _ClientInfo*>::const_iterator ii;
        for(ii = pClientsGroupInfo->m_mapAllClients.constBegin(); ii != pClientsGroupInfo->m_mapAllClients.constEnd(); ++ii)
        {
            ExitGroup(*ii, false, true);
        }*/
        while(!pClientsGroupInfo->m_mapAllClients.isEmpty())
        {
            ExitGroup(pClientsGroupInfo->m_mapAllClients.first(), false, true);
        }

        //delete (_GameGroup*)(pClientsGroupInfo->m_pClientsGroupExtraData);
        //((_GameGroup*)pClientsGroupInfo->m_pClientsGroupExtraData)->deleteLater();
        //m_poolGameGroup.releaseOneUsing((_GameGroup*)(pClientsGroupInfo->m_pClientsGroupExtraData));
        //Debug("房间释放啦1~");
        //pClientsGroupInfo->m_pClientsGroupExtraData = nullptr;

        m_Server.sendGroupInfoToAllClients(pClientsGroupInfo->m_uuid, 1);
    }

    int ret = m_Server.CloseGroup(pClientsGroupInfo);
    if(ret == 0) //关闭群
    {
        if(pClientInfo != nullptr)
        {
            m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_RESPONSE
                                                       << (qint16)GAME_SERVER_GROUP
                                                       << (qint16)GAME_SERVER_GROUP_CLOSE
                                                       << (qint16)GAME_SERVER_GROUP_CLOSE_SUCCESS;
            m_Server.m_IOCPModel.send(pClientInfo);
        }

        Info(tr("[GameServer]房间关闭:%1(%2)").arg(groupID).arg(pClientsGroupInfo->m_uuid.toString()));
    }
    else
    {
        if(pClientInfo != nullptr)
        {
            m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_RESPONSE
                                                       << (qint16)GAME_SERVER_GROUP
                                                       << (qint16)GAME_SERVER_GROUP_CLOSE
                                                       << (qint16)GAME_SERVER_GROUP_CLOSE_FAIL
                                                       << (qint16)ret;
            m_Server.m_IOCPModel.send(pClientInfo);
        }

        Critical(tr("[!GameServer]房间关闭出错:%1").arg(ret));
    }
    return ret;
}


int GameServer::SetGroupMaster(int index, _ClientsGroupInfo *pGroup, bool set)
{
    int ret;
    if(set)
        ret = pGroup->ChangeGroupMaster(index);
    else
        ret = pGroup->ChangeGroupMaster(-2);


    //发送
    QByteArray ba = pGroup->m_pIOCP->newSendData(TRANSMIT_GROUP_TYPE);
    QDataStream ds(&ba,QIODevice::ReadWrite);
    ds.device()->seek(ba.size());
    ds << (qint16)GAME_SERVER_RESPONSE
       << (qint16)GAME_SERVER_GROUP
       << (qint16)GAME_SERVER_GROUP_SETMASTER
          ;

    if(ret == 1)
    {
        _GameUserData *pGameUserData = (_GameUserData*)(pGroup->m_pGroupMaster->m_pClientExtraData);

        ds << (qint16)GAME_SERVER_GROUP_SETMASTER_SUCCESS
           << true
           //<< pGroup->m_pGroupMaster->m_SocketContext.nSocketID
           //<< pGameUserData->m_unUserGameID
           << pGroup->m_pGroupMaster->m_nIndex
           << ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->isRunning()
           << ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->m_mapGameSyncAllData.isEmpty()
              ;

        pGroup->m_pIOCP->CorrectDataLength(ba);
        pGroup->SendToGroupAllClients(ba, nullptr, -1);

        if(pGroup->m_pGroupMaster->m_ClientGroupStatus != _ClientGroupStatus::GroupStatus_Playing)
            pGroup->m_pGroupMaster->ChangeGroupStatus(_ClientGroupStatus::GroupStatus_Readying);

        Info(tr("[GameServer]设置房主成功:%1(%2),%3(%4)").arg(pGameUserData->m_strNickName).arg((int)pGroup->m_pGroupMaster).arg(((_GameGroup*)pGroup->m_pClientsGroupExtraData)->m_nGroupID).arg(pGroup->m_uuid.toString()));
    }
    else if(ret == 0)
    {
        ds << (qint16)GAME_SERVER_GROUP_SETMASTER_SUCCESS
           << false
           //<< pGroup->m_pGroupMaster->m_nIndex
           << ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->isRunning()
           << ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->m_mapGameSyncAllData.isEmpty()
              ;

        pGroup->m_pIOCP->CorrectDataLength(ba);
        pGroup->SendToGroupAllClients(ba, nullptr, -1);

        Warning(tr("[GameServer]取消房主:%1").arg(ret));
    }
    else
    {
        ds << (qint16)GAME_SERVER_GROUP_SETMASTER_FAIL << (qint16)ret;

        pGroup->m_pIOCP->CorrectDataLength(ba);
        pGroup->SendToGroupAllClients(ba);

        Critical(tr("[!GameServer]设置群主失败:%1").arg(ret));
    }

    return ret;
}


qint32 GameServer::CreateGroupHashID(int count)
{
    if(count <= 0 || count >= 10)
        return -10;

    qint32 number = 0;      //数字
    qint32 tNum = 0;        //用来判断是否循环完毕
    int i = 0;
    int maxNumber = 1;      //最大值(用来求模)

    for(number = 0, i = 0; i < count; i++)
    {
        maxNumber *= 10;
        number *= 10;
        number += qrand() % 10;
    }
    tNum = number;

    while(m_hashNumberGroups.contains(number))  //一直递增找到没有重复的位置
    {
        //QString number = QString("%1").arg(qrand() % 100, 3, 10, QChar('0'))
        //        + QString("%1").arg(qrand() % 100, 3, 10, QChar('0'));
        number = (number + 1) % maxNumber;
        if(number < 0)
            number = 0;
        if(number == tNum)
        {
            number = -11;
            break;
        }
    }

    return number;
}




void GameServer::Info(QString msg)
{
    QString current_datetime = QDateTime::currentDateTime().toString("[yyyy-MM-dd hh:mm:ss ddd]");
    ui->textDebug->append(current_datetime + msg);
    /*ui->textDebug->append(QString("%1,%2,%3,%4")
                          .arg(ui->textDebug->document()->blockCount())
                          .arg(ui->textDebug->document()->lineCount())
                          .arg(current_datetime)
                          .arg(msg)
                          );*/
    qInfo() << msg;
}

void GameServer::Debug(QString msg)
{
    //ui->textDebug->append(msg);
    qDebug() << msg;
}

void GameServer::Warning(QString msg)
{
    QString current_datetime = QDateTime::currentDateTime().toString("[yyyy-MM-dd hh:mm:ss ddd]");
    ui->textDebug->append(current_datetime + msg);
    qWarning() << msg;
}

void GameServer::Critical(QString msg)
{
    QString current_datetime = QDateTime::currentDateTime().toString("[yyyy-MM-dd hh:mm:ss ddd]");
    ui->textDebug->append(current_datetime + msg);
    qCritical() << msg;
}



//池 实现
void GameServer::onAccept(_SocketInfo::_SocketContext socketContext)
{
    //qDebug() << "QThread::currentThreadId()" << QThread::currentThreadId();

    m_Server.onAccept(socketContext);


    _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
    //((_GameUserData*)pClientInfo->m_pClientExtraData)->_pool_init();

    //pClientInfo->m_dtLogin = QDateTime::currentDateTime();

    Debug(tr("[GameServer]Accept:%1").arg((int)socketContext.pIOCPSocketContext));
}

//池 实现
void GameServer::onDisconnect(int type, _SocketInfo::_SocketContext socketContext)
{
    _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
    _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;


    //登录 游戏服务器 的 用户
    if(pGameUserData->m_unUserGameID > 0)
    {
        if(pClientInfo->m_ClientGroupStatus == GroupStatus_Playing || pClientInfo->m_ClientGroupStatus == GroupStatus_ReJoining)
        {
            bool bNetPlay = (pClientInfo->m_pGroup != nullptr);
            //UpdateScore(pClientInfo, bNetPlay, 0, 0);
        }

        u_long ip = 0;
        u_short port = 0;
        if(!m_Server.m_IOCPModel.GetSocketIPPort(&ip, &port, socketContext.pIOCPSocketContext))
            Warning(tr("[!GameServer]获取IP和Port失败"));

        //m_DatabaseSwap.insertUserOnlineLog(pGameUserData->m_unUserGameID, pClientInfo->m_nClientType, pClientInfo->m_dtLogin, QDateTime::currentDateTime());

        QMetaObject::invokeMethod(m_pDatabase,"sl_InsertUserOnlineLog"
                                  ,Qt::AutoConnection
                                  //,Q_RETURN_ARG(QVariant, v)
                                  ,Q_ARG(quint32, pGameUserData->m_unUserGameID)
                                  ,Q_ARG(qint16, pClientInfo->m_nClientType)
                                  ,Q_ARG(quint32, ip)
                                  ,Q_ARG(quint16, port)
                                  ,Q_ARG(QDateTime, pClientInfo->m_dtLogin)
                                  ,Q_ARG(QDateTime, QDateTime::currentDateTime())
                                  );

        Info(tr("[GameServer]%1 退出游戏服务器（%2，%3，%4）")
             .arg(pGameUserData->m_strUserName)
             .arg(pGameUserData->m_unID)
             .arg(pGameUserData->m_unUserGameID)
             .arg(pGameUserData->m_strNickName)
             );

        m_hashAllClientInfo.remove(pGameUserData->m_unUserGameID, pClientInfo);
    }

    if(m_ServerType == GameServer::Type_GameServer)
    {
    }
    if(m_nRecordUserOnlineLog != 0)
    {
    }


    ExitGroup(pClientInfo, true, false);

    //((_GameUserData*)pClientInfo->m_pClientExtraData)->_pool_release();
    //pClientInfo->_pool_release();

    m_Server.onDisconnect(type, socketContext);

    Debug(tr("[GameServer]CloseSocket(%1):%2").arg(type).arg((int)socketContext.pIOCPSocketContext));
}

//非池 实现
/*
void GameServer::onAccept_NonPool(_SocketInfo::_SocketContext socketContext)
{
    m_Server.onAccept(socketContext);


    _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
    pClientInfo->m_pClientExtraData = new _GameUserData;

    //pClientInfo->m_dtLogin = QDateTime::currentDateTime();

    Debug(tr("[GameServer]Accept:%1").arg((int)socketContext.pIOCPSocketContext));
}

//非池 实现
void GameServer::onDisconnect_NonPool(int type, _SocketInfo::_SocketContext socketContext)
{
    _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
    _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;

    //登录 游戏服务器 的 用户
    if(pGameUserData->m_unUserGameID > 0)
    {
        if(pClientInfo->m_ClientGroupStatus == GroupStatus_Playing)
        {
            bool bNetPlay = (pClientInfo->m_pGroup != nullptr);
            //UpdateScore(pClientInfo, bNetPlay, 3, 0);
        }

        u_long ip = 0;
        u_short port = 0;
        if(!m_Server.m_IOCPModel.GetSocketIPPort(&ip, &port, socketContext.pIOCPSocketContext))
            Warning(tr("[!GameServer]获取IP和Port失败"));

        //m_DatabaseSwap.insertUserOnlineLog(pGameUserData->m_unUserGameID, pClientInfo->m_nClientType, pClientInfo->m_dtLogin, QDateTime::currentDateTime());

        QMetaObject::invokeMethod(m_pDatabase,"sl_InsertUserOnlineLog"
                                  ,Qt::AutoConnection
                                  //,Q_RETURN_ARG(QVariant, v)
                                  ,Q_ARG(quint32, pGameUserData->m_unUserGameID)
                                  ,Q_ARG(qint16, pClientInfo->m_nClientType)
                                  ,Q_ARG(quint32, ip)
                                  ,Q_ARG(quint16, port)
                                  ,Q_ARG(QDateTime, pClientInfo->m_dtLogin)
                                  ,Q_ARG(QDateTime, QDateTime::currentDateTime())
                                  );

        Info(tr("[GameServer]%1 退出游戏服务器（%2，%3，%4）")
             .arg(pGameUserData->m_strUserName)
             .arg(pGameUserData->m_unID)
             .arg(pGameUserData->m_unUserGameID)
             .arg(pGameUserData->m_strNickName)
             );

    }

    if(m_ServerType == GameServer::Type_GameServer)
    {
    }
    if(m_nRecordUserOnlineLog != 0)
    {
    }


    _ClientsGroupInfo *pGroup = pClientInfo->m_pGroup;
    if(pGroup != nullptr)
    {
        ExitGroup(pClientInfo, false);
    }

    delete (_GameUserData*)pClientInfo->m_pClientExtraData;
    delete pClientInfo;

    //m_mapAllClients.removeOne(pClientInfo);
    m_mapAllClients.remove(socketContext.pIOCPSocketContext);


    Debug(tr("[GameServer]CloseSocket(%1):%2").arg(type).arg((int)socketContext.pIOCPSocketContext));
}
*/

void GameServer::onReadyRead(QByteArray baData, quint8 controlByte, _SocketInfo::_SocketContext socketContext)
{
    //qDebug()<<"ThreadId:"<<::GetCurrentThreadId();
    Debug(tr("[GameServer]Net Data Coming...:%1(%2)").arg(controlByte).arg(baData.length()));

    _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
    _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;
    _ClientsGroupInfo *pGroup = pClientInfo->m_pGroup;
    _GameGroup *pGameGroup = nullptr;
    if(nullptr != pGroup)
        pGameGroup = ((_GameGroup*)pGroup->m_pClientsGroupExtraData);

    //QDataStream dsData(baData);   //ERROR!
    QDataStream dsData(&baData,QIODevice::ReadOnly);    //ReadWrite
    qint16 netType;

    //qDebug() << baData.toHex();
    //while(!dsData.atEnd())
    if(!dsData.atEnd())
    {
        //解密
        switch(controlByte)
        {
        case TRANSMIT_CODE_DATA:
            //qDebug() << baData.toHex();
            if(!m_Server.RecieveUseTransfersCode(pClientInfo, baData))
                return;
            break;
        default:
            break;
        }

        /*
        QFile netLog("netLog.log");
        if(controlByte == TRANSMIT_CODE_DATA)
            netLog.setFileName("netsLog.log");
        netLog.open(QIODevice::Append);
        netLog.write(baData.toHex());
        netLog.write("\r\n--------------------------\r\n");
        netLog.close();
        */

        dsData >> netType;
        Debug(tr("[GameServer]Net Data Type:%1").arg(netType));
        switch(netType)
        {
        case INFO_SERVER_REQUEST:
            {
                dsData >> netType;
                switch(netType)
                {
                case INFO_SERVER_CLIENT:
                    {
                        dsData >> netType;
                        switch(netType)
                        {
                        case INFO_SERVER_CLIENT_LOGIN:
                            {
                                QString password;
                                dsData >> pGameUserData->m_strUserName
                                        >> password
                                        >> pClientInfo->m_nClientType
                                        >> pGameUserData->m_nVersion
                                        ;

                                pGameUserData->m_strUserName = pGameUserData->m_strUserName.replace(QChar('\''),"");

                                //int ret = sendUserInfo(pClientInfo, password);
                                QMetaObject::invokeMethod(m_pDatabase,"sl_QueryUser"
                                                          ,Qt::AutoConnection
                                                          //,Q_RETURN_ARG(QVariant, v)
                                                          ,Q_ARG(QString, pGameUserData->m_strUserName)
                                                          ,Q_ARG(QString, password)
                                                          ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_CLIENT_TYPE))
                                                          ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                                          );
                                /*
                                pClientInfo->dsOut.device()->reset();
                                pClientInfo->baOut.clear();*/
                            }
                            break;

                        case INFO_SERVER_CLIENT_REGISTER:
                            {
                                QString password;
                                dsData >> pGameUserData->m_strUserName
                                        //>> pGameUserData->m_strNickName
                                        >> password
                                        >> pGameUserData->m_nSex
                                        >> pClientInfo->m_nClientType
                                        >> pGameUserData->m_nVersion
                                        ;
                                pGameUserData->m_strUserName = pGameUserData->m_strUserName.replace(QChar('\''),"");
                                pGameUserData->m_strNickName = pGameUserData->m_strNickName.replace(QChar('\''),"");

                                //int ret = sendRegisterUserInfo(pClientInfo, password);
                                QMetaObject::invokeMethod(m_pDatabase,"sl_RegisterUser"
                                                          ,Qt::AutoConnection
                                                          //,Q_RETURN_ARG(QVariant, v)
                                                          ,Q_ARG(QString, pGameUserData->m_strUserName)
                                                          ,Q_ARG(QString, password)
                                                          ,Q_ARG(qint16, pGameUserData->m_nSex)
                                                          ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_CLIENT_TYPE))
                                                          ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                                          );
                            }
                            break;

                            /*
                        case INFO_SERVER_CLIENT_SERVERINFO:
                            {
                                m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_CLIENT_RESPONSE << (qint16)INFO_SERVER_CLIENT
                                    << (qint16)INFO_SERVER_CLIENT_SERVERINFO;

                                int ret = m_DatabaseSwap.getGameServerInfoToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo));
                                switch(ret) {
                                case 0:
                                    Debug(tr("[GameServer]获取ServerInfo"));
                                    break;
                                default:
                                    {
                                        Critical(tr("[!GameServer]服务器{获取ServerInfo}ERROR:%1").arg(ret));
                                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_SERVERINFO_FAIL;
                                    }
                                }
                                m_Server.m_IOCPModel.send(pClientInfo);
                            }
                            break;
                            */
                        default:
                            Critical(tr("[!GameServer]INFO_SERVER_CLIENT ERROR:%1").arg(netType));
                            break;
                        }
                    }
                    break;

                default:
                    Critical(tr("[!GameServer]INFO_SERVER_REQUEST ERROR:%1").arg(netType));
                    break;
                }
            }
            break;
        case GAME_SERVER_REQUEST:
            {
                dsData >> netType;
                switch(netType)
                {
                case GAME_SERVER_CLIENT:
                    {
                        dsData >> netType;
                        switch(netType)
                        {
                        //获取玩家信息
                        case GAME_SERVER_CLIENT_GAMEUSERINFO:
                            {
                                QString serverKey;
                                dsData >> pGameUserData->m_unID >> pGameUserData->m_strUserName >> pGameUserData->m_nServerID >> serverKey >> pClientInfo->m_nClientType >> pGameUserData->m_nVersion;

                                //int ret = m_DatabaseSwap.getGameUserInfoToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo), userID, serverID, gradeID, serverKey, pClientInfo);
                                QMetaObject::invokeMethod(m_pDatabase,"sl_GetGameUserInfoToBuffer"
                                                          ,Qt::AutoConnection
                                                          //,Q_RETURN_ARG(QVariant, v)
                                                          ,Q_ARG(quint32, pGameUserData->m_unID)
                                                          ,Q_ARG(qint32, pGameUserData->m_nServerID)
                                                          ,Q_ARG(QString, serverKey)
                                                          ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_CLIENT_TYPE))
                                                          ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                                          );
                            }
                            break;

                        //注册玩家号(在GAME_SERVER_CLIENT_GAMEUSERINFO执行之后)
                        case GAME_SERVER_CLIENT_REGISTERGAMEUSERINFO:
                            {
                                quint32 userID;
                                qint32 serverID;
                                dsData >> userID >> serverID >> pGameUserData->m_strNickName >> pGameUserData->m_nSex >> pClientInfo->m_nClientType >> pGameUserData->m_nVersion;

                                //int ret = m_DatabaseSwap.registerGameUser(userID, serverID, nickName, sex, m_Server.m_IOCPModel.sendData(pClientInfo), pClientInfo);
                                QMetaObject::invokeMethod(m_pDatabase,"sl_RegisterGameUser"
                                                          ,Qt::AutoConnection
                                                          //,Q_RETURN_ARG(QVariant, v)
                                                          ,Q_ARG(quint32, pGameUserData->m_unID)
                                                          ,Q_ARG(qint32, pGameUserData->m_nServerID)
                                                          ,Q_ARG(QString, pGameUserData->m_strNickName)
                                                          ,Q_ARG(qint16, pGameUserData->m_nSex)
                                                          ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_CLIENT_TYPE))
                                                          ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                                          );
                            }
                            break;



                        case GAME_SERVER_CLIENT_SHAREEXTRAGAMEDATA_SET:
                            {
                                QString key;
                                QVariant data;
                                bool saveToDB;
                                dsData >> key >> data >> saveToDB;

                                pGameUserData->m_vExtraData = data;

                                if(saveToDB)
                                    QMetaObject::invokeMethod(m_pDatabase,"sl_SetClientShareExtraGameData"
                                                              ,Qt::AutoConnection
                                                              //,Q_RETURN_ARG(QVariant, v)
                                                              ,Q_ARG(quint32, pGameUserData->m_unUserGameID)
                                                              ,Q_ARG(QString, key)
                                                              ,Q_ARG(QVariant, data)
                                                              ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_CLIENT_TYPE))
                                                              ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                                              );
                            }
                            break;

                        //游戏数据
                        case GAME_SERVER_GETDATA:
                            {
                                qint32 dataType, dataValue;
                                QString key;
                                qint32 operationID;
                                dsData >> dataType >> dataValue >> key >> operationID;

                                QMetaObject::invokeMethod(m_pDatabase,"sl_GetClientGameData"
                                                          ,Qt::AutoConnection
                                                          //,Q_RETURN_ARG(QVariant, v)
                                                          ,Q_ARG(quint32, pGameUserData->m_unUserGameID)
                                                          ,Q_ARG(qint32, dataType)
                                                          ,Q_ARG(qint32, dataValue)
                                                          ,Q_ARG(QString, key)
                                                          ,Q_ARG(qint32, operationID)
                                                          ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_DATA_TYPE))
                                                          ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                                          );
                            }
                            break;

                        case GAME_SERVER_SETDATA:
                            {
                                qint32 dataType, dataValue;
                                QString key;
                                QVariant data;
                                qint32 operationID;
                                dsData >> dataType >> dataValue >> key >> data >> operationID;

                                QMetaObject::invokeMethod(m_pDatabase,"sl_SetClientGameData"
                                                          ,Qt::AutoConnection
                                                          //,Q_RETURN_ARG(QVariant, v)
                                                          ,Q_ARG(quint32, pGameUserData->m_unUserGameID)
                                                          ,Q_ARG(qint32, dataType)
                                                          ,Q_ARG(qint32, dataValue)
                                                          ,Q_ARG(QString, key)
                                                          ,Q_ARG(QVariant, data)
                                                          ,Q_ARG(qint32, operationID)
                                                          ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_DATA_TYPE))
                                                          ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                                          );
                            }
                            break;

                        case GAME_SERVER_DELETEDATA:
                            {
                                qint32 dataType, dataValue;
                                qint32 operationID;
                                dsData >> dataType >> dataValue >> operationID;

                                QMetaObject::invokeMethod(m_pDatabase,"sl_DeleteClientGameData"
                                                          ,Qt::AutoConnection
                                                          //,Q_RETURN_ARG(QVariant, v)
                                                          ,Q_ARG(quint32, pGameUserData->m_unUserGameID)
                                                          ,Q_ARG(qint32, dataType)
                                                          ,Q_ARG(qint32, dataValue)
                                                          ,Q_ARG(qint32, operationID)
                                                          ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_DATA_TYPE))
                                                          ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                                          );
                            }
                            break;



                        case GAME_SERVER_INSERTDATA:
                            {
                                qint32 dataType, dataValue;
                                QVariant data;
                                qint32 operationID;
                                dsData >> dataType >> dataValue >> data >> operationID;

                                QMetaObject::invokeMethod(m_pDatabase,"sl_InsertClientData"
                                                          ,Qt::AutoConnection
                                                          //,Q_RETURN_ARG(QVariant, v)
                                                          ,Q_ARG(quint32, pGameUserData->m_unUserGameID)
                                                          ,Q_ARG(qint32, dataType)
                                                          ,Q_ARG(qint32, dataValue)
                                                          ,Q_ARG(QVariant, data)
                                                          ,Q_ARG(qint32, operationID)
                                                          ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_DATA_TYPE))
                                                          ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                                          );
                            }
                            break;

                        case GAME_SERVER_UPDATEDATA:
                            {
                                qint32 dataType,dataValue;
                                QVariant data;
                                qint32 operationID;
                                dsData >> dataType >> dataValue >> data >> operationID;

                                QMetaObject::invokeMethod(m_pDatabase,"sl_UpdateClientData"
                                                          ,Qt::AutoConnection
                                                          //,Q_RETURN_ARG(QVariant, v)
                                                          ,Q_ARG(quint32, pGameUserData->m_unUserGameID)
                                                          ,Q_ARG(qint32, dataType)
                                                          ,Q_ARG(qint32, dataValue)
                                                          ,Q_ARG(QVariant, data)
                                                          ,Q_ARG(qint32, operationID)
                                                          ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_DATA_TYPE))
                                                          ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                                          );
                            }
                            break;


                        case GAME_SERVER_DBQUERY:
                            {
                                qint32 dataValue;
                                QString strQuery;
                                qint32 operationID;
                                dsData >> dataValue >> strQuery >> operationID;

                                QMetaObject::invokeMethod(m_pDatabase,"sl_DBQuery"
                                                          ,Qt::AutoConnection
                                                          //,Q_RETURN_ARG(QVariant, v)
                                                          ,Q_ARG(qint32, dataValue)
                                                          ,Q_ARG(QString, strQuery)
                                                          ,Q_ARG(qint32, operationID)
                                                          ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData(TRANSMIT_DATA_TYPE))
                                                          ,Q_ARG(_SocketInfo::_SocketContext, socketContext)
                                                          );
                            }
                            break;

                        default:
                            break;
                        }
                    }
                    break;



                case GAME_SERVER_GROUP:
                    {
                        dsData >> netType;
                        switch(netType)
                        {
                        /*case GAME_SERVER_SERVERINFO:
                            {
                                _GameData *pData;
                                pData = new _GameData;
                                if(pData == nullptr)
                                {
                                    pGameGroup->TerminateGame(-20, GameCore::Game_Status_ERROR);
                                    return;
                                }

                                pData->sender = pClientInfo;
                                pData->type = netType;

                                dsData >> pData->iAnswer;

                                if(!pData->CheckGameData())
                                {
                                    if(pData != nullptr)delete pData;
                                    pGameGroup->TerminateGame(-11, GameCore::Game_Status_ERROR);
                                    return;
                                }

                                Debug(tr("[GameServer]回答接受保存到队列"));
                                pGameGroup->m_Producer.safeIn(pData);
                                Debug(tr("[GameServer]回答接受完毕"));
                            }
                            break;*/




                    //房间功能
                        //创建房间
                        case GAME_SERVER_GROUP_CREATE:
                            {
                                qint32 playerMaxCount, playerWatchingMaxCount;
                                QString password;
                                qint32 type;
                                QVariant vData;
                                dsData >> playerMaxCount >> playerWatchingMaxCount >> password >> type >> vData;


                                _ClientsGroupInfo *pGroup1 = nullptr;
                                qint32 groupID = CreateGroup(pClientInfo,playerMaxCount,playerWatchingMaxCount,password,CreateGroupHashID(6),type,vData);
                                //qint32 groupID = CreateGroup(pClientInfo,playerMaxCount,password,pClientInfo->m_SocketContext.nSocketID);

                                if(groupID >= 0)
                                {
                                    QUuid uid = m_hashNumberGroups.value(groupID);
                                    pGroup1 = m_Server.GetGroup(uid);
                                    //pGroup1 = m_hashNumberGroups.value(groupID, nullptr);
                                }

                                if(pGroup1 != nullptr)
                                {
                                    //_GameGroup *p = new _GameGroup;
                                    //_GameGroup *p = m_poolGameGroup.getOneEmpty();
                                    //pGroup1->m_pClientsGroupExtraData = p;
                                    _GameGroup *p = (_GameGroup*)pGroup1->m_pClientsGroupExtraData;

                                    //如果是新创建节点：
                                    if(((_LMS_Pool<_ClientsGroupInfo>::_Data*)pGroup1)->SetNewNode(false))
                                    //if(p->_pool_newNode())  //如果是新节点
                                    {
                                        p->m_pClientsGroupInfo = pGroup1;
                                        p->m_nFrameSendInterval = this->m_nFrameSendInterval;


                                        connect(p, &_GameGroup::s_Info, this, &GameServer::Info);
                                        connect(p, &_GameGroup::s_Debug, this, &GameServer::Debug);
                                        connect(p, &_GameGroup::s_Warning, this, &GameServer::Warning);
                                        connect(p, &_GameGroup::s_Critical, this, &GameServer::Critical);


                                        //p->m_pGameModel = new GameModel(p);
                                        //if(p->m_pGameModel != nullptr)
                                        {
                                            connect(p, &GameModel::s_Message, this, [=](QString msg) {
                                                qDebug() << msg;
                                            });
                                            connect(p, &GameModel::s_Debug, this, &GameServer::Debug);
                                            connect(p, &GameModel::s_Critical, this, &GameServer::Critical);

                                            connect(p, &GameModel::s_GameOver, p, &_GameGroup::GameOver);

                                        }

                                        //qRegisterMetaType<QByteArray>("QByteArray");      //qml中使用其函数
                                        /*connect(p, &_GameGroup::s_SendToGroupAllClients, p, [p](QByteArray ba, _ClientInfo *pClientInfo)
                                        {
                                                p->m_pClientsGroupInfo->SendToGroupAllClients(ba, pClientInfo);
                                        });*/

                                        p->InitOnce();
                                        //p->_pool_setNewNode(false);
                                    }
                                    //p->m_nType = type;


                                    int ret = JoinGroup(pClientInfo, groupID, password, 0);
                                    if(ret < 0)
                                        CloseGroup(pGroup1);
                                    //else
                                    //    SetGroupMaster(pClientInfo, pGroup1, false);

                                    /*if(ret >= 0)
                                    {
                                        Debug(tr("[GameServer]创建一个房间并加入成功:%1(%2)").arg(groupID).arg(pGroup1->m_uuid.toString()));
                                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_GROUP_CREATE_SUCCESS
                                                                                   << groupID;
                                        m_Server.m_IOCPModel.send(pClientInfo);
                                        m_Server.sendGroupInfoToAllClients(pGroup1);
                                    }
                                    else
                                    {
                                        Critical(tr("[!GameServer]创建房间成功,加入失败:%1").arg(ret));
                                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_GROUP_CREATE_FAIL
                                                                                   << (qint16)ret;
                                        m_Server.m_IOCPModel.send(pClientInfo);
                                        CloseGroup(pGroup1);
                                    }*/
                                }
                                /*else
                                {
                                    Critical(tr("[!GameServer]创建一个房间失败:%1").arg(groupID));
                                    m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_GROUP_CREATE_FAIL
                                                                               << (qint16)groupID;
                                    m_Server.m_IOCPModel.send(pClientInfo);
                                }*/
                            }
                            break;

                        case GAME_SERVER_GROUP_UPDATE:
                            {
                                bool lock;
                                bool autoClose;

                                dsData >> lock >> autoClose;

                                if(pGroup != nullptr)
                                {
                                    if(autoClose)
                                        pGroup->m_flagStatus |= _ClientsGroupInfo::Status_AutoClose;
                                    else
                                        pGroup->m_flagStatus &= ~_ClientsGroupInfo::Status_AutoClose;

                                    if(lock)
                                        pGroup->m_flagStatus |= _ClientsGroupInfo::Status_Locked;
                                    else
                                        pGroup->m_flagStatus &= ~_ClientsGroupInfo::Status_Locked;

                                    m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_RESPONSE
                                                                               << (qint16)GAME_SERVER_GROUP
                                                                               << (qint16)GAME_SERVER_GROUP_UPDATE
                                                                               << (qint16)GAME_SERVER_GROUP_UPDATE_SUCCESS
                                                                               ;
                                    m_Server.m_IOCPModel.send(pClientInfo);
                                    Info(tr("[GameServer]房间属性更新:%1,%2,%3").arg(lock).arg(autoClose).arg(pGroup->m_pGroupMaster == pClientInfo));
                                }
                                else
                                {
                                    m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_RESPONSE
                                                                               << (qint16)GAME_SERVER_GROUP
                                                                               << (qint16)GAME_SERVER_GROUP_UPDATE
                                                                               << (qint16)GAME_SERVER_GROUP_UPDATE_FAIL
                                                                               << (qint16)-1;
                                    m_Server.m_IOCPModel.send(pClientInfo);
                                    Warning(tr("[!GameServer]房间属性更新:%1 没有加入房间").arg(pGameUserData->m_strNickName));
                                }
                            }
                            break;

                        case GAME_SERVER_GROUP_CLOSE:
                            {
                                qint32 groupID;
                                dsData >> groupID;

                                _ClientsGroupInfo *pGroup1 = nullptr;
                                if(groupID == -1)
                                {
                                    pGroup1 = pGroup;
                                }
                                else
                                {
                                    QUuid uuid = m_hashNumberGroups.value(groupID, QUuid());
                                    pGroup1 = m_Server.GetGroup(uuid);
                                }
                                CloseGroup(pGroup1, pClientInfo);
                            }
                            break;

                        //退房间
                        case GAME_SERVER_GROUP_EXITGROUP:
                            {
                                ExitGroup(pClientInfo, false, false);
                            }
                            break;

                        //群消息
                        case GAME_SERVER_GROUP_MESSAGE:
                            {
                                quint32 userGameID;
                                qint16 type;
                                QString message;
                                dsData >> userGameID >> type >> message;
                                if(pGroup != nullptr)
                                {
                                    //发送
                                    QByteArray ba = pGroup->m_pIOCP->newSendData(TRANSMIT_GROUP_TYPE);
                                    QDataStream ds(&ba,QIODevice::ReadWrite);
                                    ds.device()->seek(ba.size());
                                    ds << (qint16)GAME_SERVER_RESPONSE
                                       << (qint16)GAME_SERVER_GROUP
                                       << (qint16)GAME_SERVER_GROUP_OTHERSINFO
                                       << (qint16)GAME_SERVER_GROUP_OTHERSINFO_MESSAGE
                                       << userGameID
                                       << (qint16)type
                                       << message
                                          ;
                                    pGroup->m_pIOCP->CorrectDataLength(ba);
                                    pGroup->SendToGroupAllClients(ba, pClientInfo);

                                }
                            }
                            break;

                        //加入房间
                        case GAME_SERVER_GROUP_JOINGROUP:
                            {
                                qint32 groupID;
                                QString password;
                                bool forceJoin;     //强制加入(忽略玩家是否已加入一个房间)
                                qint32 joinType;

                                dsData >> groupID >> password >> forceJoin >> joinType >> pGameUserData->m_nGroupType;

                                int ret;
                                if(forceJoin)
                                {
                                    _ClientsGroupInfo* pGroup1 = m_Server.SearchGroup(pClientInfo, password);
                                    if(pGroup1 != nullptr)
                                    {
                                        ExitGroup(pClientInfo, false, false);
                                        ret = JoinGroup(pClientInfo, ((_GameGroup*)pGroup1->m_pClientsGroupExtraData)->m_nGroupID, password, joinType);
                                    }
                                    else
                                    {
                                        //加入失败，指定个不存在的groupID
                                        ret = JoinGroup(pClientInfo, -2, password, joinType);
                                    }
                                }
                                else
                                    ret = JoinGroup(pClientInfo, groupID, password, joinType);

                                /*if(ret >= 0)
                                {
                                }
                                else
                                {
                                }*/
                                //return ret;
                            }
                            break;

                        //重新加入房间
                        case GAME_SERVER_GROUP_REJOINRUNNINGGROUP:
                            {
                                qint32 groupID, oldGroupIndex, oldSocketID;

                                dsData >> groupID >> oldGroupIndex >> oldSocketID;

                                int ret = ReJoinRunningGroup(pClientInfo, oldGroupIndex, oldSocketID, groupID);

                                if(ret == 0)
                                {
                                    pGroup = pClientInfo->m_pGroup;
                                    pGameGroup = ((_GameGroup*)pGroup->m_pClientsGroupExtraData);

                                    Info(tr("[GameServer]%1 重新加入房间成功(%2,%3):%4").arg(pGameUserData->m_strNickName).arg(oldGroupIndex).arg(oldSocketID).arg(groupID));

                                    //发送
                                    m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                                            << (qint16)GAME_SERVER_RESPONSE
                                            << (qint16)GAME_SERVER_GROUP
                                            << (qint16)GAME_SERVER_GROUP_REJOINRUNNINGGROUP
                                            << (qint16)GAME_SERVER_GROUP_REJOINRUNNINGGROUP_SUCCESS
                                            << pClientInfo->m_SocketContext.nSocketID
                                            << pClientInfo->m_nIndex
                                            << oldSocketID
                                               ;


                                    //给新客户 发送 群内所有客户信息（包括自己）
                                    qint32 count = pGroup->m_mapAllClients.count();
                                    m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                                            << (qint32)count;

                                    _GameUserData *pGUD = nullptr;

                                    QMap<qint32, _ClientInfo*>::const_iterator ii;
                                    for(ii = pGroup->m_mapAllClients.constBegin(); ii != pGroup->m_mapAllClients.constEnd(); ++ii)
                                    {
                                        pGUD = ((_GameUserData*)((*ii)->m_pClientExtraData));

                                        m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                                                << (*ii)->m_SocketContext.nSocketID
                                                << (*ii)->m_nIndex
                                                << pGUD->m_unUserGameID
                                                << (pGroup->m_pGroupMaster == (*ii))
                                                << (qint16)((*ii)->m_ClientGroupStatus)
                                                << pGUD->m_strNickName
                                                << pGUD->m_nSex
                                                << pGUD->m_nScore
                                                << pGUD->m_nServerID
                                                << pGUD->m_vExtraData
                                                   ;
                                    }

                                    m_Server.m_IOCPModel.send(pClientInfo);



                                    //给群里其他客户发送 新客户信息
                                    QByteArray ba = pClientInfo->m_pGroup->m_pIOCP->newSendData(TRANSMIT_GROUP_TYPE);
                                    QDataStream ds(&ba,QIODevice::ReadWrite);
                                    ds.device()->seek(ba.size());
                                    ds << (qint16)GAME_SERVER_RESPONSE
                                       << (qint16)GAME_SERVER_GROUP
                                       << (qint16)GAME_SERVER_GROUP_OTHERSINFO
                                       << (qint16)GAME_SERVER_GROUP_OTHERSINFO_REJOINRUNNINGGROUP
                                       << pClientInfo->m_SocketContext.nSocketID
                                       << pClientInfo->m_nIndex
                                       << oldSocketID
                                       << pGameUserData->m_unUserGameID
                                       << ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->isRunning()
                                       << ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->m_bResetFrameWhenClientExitGroup
                                       << (bool)true    //加入

                                       /*<< (pGroup->m_pGroupMaster == pClientInfo)
                                       << pGameUserData->m_strNickName
                                       << pGameUserData->m_nSex
                                       << pGameUserData->m_nScore
                                       << pGameUserData->m_nServerID
                                       << pGameUserData->m_vExtraData*/
                                          ;
                                    pClientInfo->m_pGroup->m_pIOCP->CorrectDataLength(ba);
                                    pClientInfo->m_pGroup->SendToGroupAllClients(ba, pClientInfo, -1);


                                    m_Server.sendClientJoinInfoToAllClients(pClientInfo);

                                }
                                else
                                {
                                    Warning(tr("[!GameServer]%1 重新加入房间失败(%2,%3,%4):%5").arg(pGameUserData->m_strNickName).arg(groupID).arg(oldGroupIndex).arg(oldSocketID).arg(ret));

                                    m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_RESPONSE
                                                                               << (qint16)GAME_SERVER_GROUP
                                                                               << (qint16)GAME_SERVER_GROUP_REJOINRUNNINGGROUP
                                                                               << (qint16)GAME_SERVER_GROUP_REJOINRUNNINGGROUP_FAIL
                                                                               << (qint16)ret;
                                    m_Server.m_IOCPModel.send(pClientInfo);
                                }
                            }
                            break;

                        //释放某个已经掉线的座位
                        case GAME_SERVER_GROUP_RELEASEGROUPINDEX:
                            {
                                qint32 oldGroupIndex;
                                quint32 oldUserGameID;

                                dsData >> oldGroupIndex >> oldUserGameID;

                                int ret = ReleaseGroupIndex(oldGroupIndex, oldUserGameID, pGroup);

                                if(ret == 0)
                                {
                                    Info(tr("[GameServer]%1 释放房间Index成功(%2,%3)").arg(pGameUserData->m_strNickName).arg(oldGroupIndex).arg(oldUserGameID));
                                    //pGameGroup->ClientExitRunningGroup();
                                }
                                else
                                {
                                    Warning(tr("[!GameServer]%1 释放房间Index失败(%2,%3):%4").arg(pGameUserData->m_strNickName).arg(oldGroupIndex).arg(oldUserGameID).arg(ret));

                                    m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_RESPONSE
                                                                               << (qint16)GAME_SERVER_GROUP
                                                                               << (qint16)GAME_SERVER_GROUP_RELEASEGROUPINDEX
                                                                               << (qint16)GAME_SERVER_GROUP_RELEASEGROUPINDEX_FAIL
                                                                               << (qint16)ret;
                                    m_Server.m_IOCPModel.send(pClientInfo);
                                }

                            }
                            break;

                        //准备
                        case GAME_SERVER_GROUP_GETREADY:
                            {
                                //_GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

                                dsData >> pGameUserData->m_nDuiWu;

                                int ret = -2;
                                //判断原来是否有房间
                                if(pGroup != nullptr)
                                {
                                    ret = pClientInfo->ChangeGroupStatus();
                                }

                                switch (ret)
                                {
                                case 0:
                                    {
                                        //发送
                                        QByteArray ba = pGroup->m_pIOCP->newSendData(TRANSMIT_GROUP_TYPE);
                                        QDataStream ds(&ba,QIODevice::ReadWrite);
                                        ds.device()->seek(ba.size());
                                        ds << (qint16)GAME_SERVER_RESPONSE
                                           << (qint16)GAME_SERVER_GROUP
                                           << (qint16)GAME_SERVER_GROUP_GETREADY
                                           << (qint16)GAME_SERVER_GROUP_GETREADY_SUCCESS
                                           //<< pClientInfo->m_SocketContext.nSocketID
                                           //<< pGameUserData->m_unUserGameID
                                           << pClientInfo->m_nIndex
                                           << (qint16)pClientInfo->m_ClientGroupStatus
                                              ;

                                        pGroup->m_pIOCP->CorrectDataLength(ba);
                                        pGroup->SendToGroupAllClients(ba);



                                        m_Server.sendClientReadyInfoToAllClients(pClientInfo);

                                        Debug(tr("[GameServer]客户切换状态成功:%1").arg(pClientInfo->m_ClientGroupStatus));
                                        break;
                                    }
                                case -1:
                                    {
                                        m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                                                << (qint16)GAME_SERVER_RESPONSE
                                                << (qint16)GAME_SERVER_GROUP
                                                << (qint16)GAME_SERVER_GROUP_GETREADY
                                                << (qint16)GAME_SERVER_GROUP_GETREADY_FAIL
                                                << (qint16)ret;
                                        m_Server.m_IOCPModel.send(pClientInfo);

                                        qint32 groupID = 0;
                                        QString groupUuid;
                                        if(pGroup != nullptr)
                                        {
                                            groupID = pGameGroup->m_nGroupID;
                                            groupUuid = pGroup->m_uuid.toString();
                                        }

                                        Critical(tr("[!GameServer]客户切换状态失败1:%1,%2,%3(%4)")
                                                 .arg(pGameUserData->m_strNickName)
                                                 .arg(pClientInfo->m_ClientGroupStatus)
                                                 .arg(groupID)
                                                 .arg(groupUuid)
                                                 );
                                    }
                                    break;
                                default:
                                    m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE)
                                            << (qint16)GAME_SERVER_RESPONSE
                                            << (qint16)GAME_SERVER_GROUP
                                            << (qint16)GAME_SERVER_GROUP_GETREADY
                                            << (qint16)GAME_SERVER_GROUP_GETREADY_FAIL
                                            << (qint16)ret;
                                    m_Server.m_IOCPModel.send(pClientInfo);

                                    Critical(tr("[!GameServer]客户切换状态失败2:%1").arg(ret));
                                    break;
                                }


                                //QByteArray ba = m_IOCPModel.newSendData(TRANSMIT_GROUP_TYPE);
                                //QDataStream ds(&ba,QIODevice::ReadWrite);
                                //ds.device()->seek(ba.size());

                                //m_pClientsGroupInfo->m_pIOCP->CorrectDataLength(ba);
                                //pGroup->SendToGroupAllClients(ds, pClientInfo);
                                ////sendToAllClientInGroup(ba, pClientInfo);

                            }
                            break;

                        //踢人
                        case GAME_SERVER_GROUP_KICK:
                            {
                                int ret;
                                qint32 socketID;
                                dsData >> socketID;
                                _ClientInfo *pClientInfo1 = m_Server.m_mapAllClients.value(socketID, nullptr);
                                if(nullptr != pClientInfo1)
                                {
                                    ret = ExitGroup(pClientInfo1, false, false);
                                    if(ret >= 0)
                                    {
                                        m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_RESPONSE
                                                                                   << (qint16)GAME_SERVER_GROUP
                                                                                   << (qint16)GAME_SERVER_GROUP_KICK
                                                                                   << (qint16)GAME_SERVER_GROUP_KICK_SUCCESS;
                                        m_Server.m_IOCPModel.send(pClientInfo);
                                        Debug(tr("[GameServer]踢人成功:%1").arg(socketID));
                                    }
                                    else
                                    {
                                        m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_RESPONSE
                                                                                   << (qint16)GAME_SERVER_GROUP
                                                                                   << (qint16)GAME_SERVER_GROUP_KICK
                                                                                   << (qint16)GAME_SERVER_GROUP_KICK_FAIL
                                                                                   << (qint16)ret;
                                        m_Server.m_IOCPModel.send(pClientInfo);
                                        Warning(tr("[!GameServer]踢人%1失败:%2").arg(socketID).arg(ret));
                                    }
                                }
                                else
                                {
                                    m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GROUP_TYPE) << (qint16)GAME_SERVER_RESPONSE
                                                                               << (qint16)GAME_SERVER_GROUP
                                                                               << (qint16)GAME_SERVER_GROUP_KICK
                                                                               << (qint16)GAME_SERVER_GROUP_KICK_FAIL
                                                                               << (qint16)-100;
                                    m_Server.m_IOCPModel.send(pClientInfo);
                                    Warning(tr("[!GameServer]踢人失败:没有%1").arg(socketID));
                                }
                            }
                            break;


                        /*
                        case GAME_SERVER_:
                            {
                                //dsData >> var;
                                m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                                                                  << (qint16)GAME_SERVER_GROUP
                                                                  << (qint16)GAME_SERVER_GROUP_EXITGROUP;
                            }
                            break;
                            */

                        default:
                            Critical(tr("[!GameServer]GAME_SERVER_GROUP ERROR:%1").arg(netType));
                            break;
                        }
                    }
                    break;

                default:
                    Critical(tr("[!GameServer]GAME_SERVER_REQUEST ERROR:%1").arg(netType));
                    break;
                }
            }
            break;


        case GAME_DATA:
            {
                if(pClientInfo == nullptr)
                {
                    Warning(tr("[!GameServer]WARNING!指针为nullptr:%1").arg((int)pClientInfo));
                    return;
                }
                /*if(!(pGroup->m_flagStatus & _ClientsGroupInfo::Status_Locked))
                {
                    Warning(tr("[!GameServer]WARNING!接收GAME包时Group状态为Unlocked:%1").arg(pGroup->m_flagStatus));
                    return;
                }
                if(pGameGroup->m_GameModel.gameStatus() != GameModel::Game_Status_Running)
                {
                    Warning(tr("[!GameServer]WARNING!接收GAME包时Game已经结束:%1").arg(pGameGroup->m_GameModel.gameStatus()));
                    return;
                }*/

                dsData >> netType;
                Debug(tr("[GameServer]GAME_DATA:%1").arg(netType));
                switch(netType)
                {
                //游戏开始
                case GAME_DATA_STARTGAME:
                    {
                        int ret;
                        if(pClientInfo == nullptr)
                            ret = -10;
                        else
                        {
                            qint16 type;
                            dsData >> type;

                            if(pGroup == nullptr)   //单人游戏
                            {
                                pClientInfo->ChangeGroupStatus(_ClientGroupStatus::GroupStatus_Playing);
                                Info(tr("[GameServer]单人游戏开始:%1").arg(pGameUserData->m_strNickName));
                                break;
                            }
                            else    //多人游戏
                            {
                                ret = pGameGroup->StartGame(type);
                            }
                        }

                        switch (ret)
                        {
                        case 0:
                            {
                                //pGroup->StartGameModel(pClientInfo);
                                Debug(tr("[GameServer]游戏开始!"));
                            }
                            break;
                        default:
                            m_Server.m_IOCPModel.sendData(pClientInfo, TRANSMIT_GAME_TYPE) << (qint16)GAME_DATA
                                                                       << (qint16)GAME_DATA_STARTGAME
                                                                       << (qint16)GAME_DATA_STARTGAME_FAIL
                                                                       << (qint16)ret;
                            m_Server.m_IOCPModel.send(pClientInfo);
                            break;
                        }

                    }
                    break;

                //游戏初始化结束
                case GAME_DATA_INITOVER:
                    {
                        /*
                        //quint32 gameID;
                        //dsData >> gameID;

                        if(pClientInfo == nullptr || pGroup == nullptr)
                            break;

                        int uninitCount = 0;
                        QMap<qint32, _ClientInfo*>::const_iterator ii;
                        for(ii = pGroup->m_mapAllClients.constBegin(); ii != pGroup->m_mapAllClients.constEnd(); ++ii)
                        {
                            //if(pGameUserData->m_unUserGameID == ((_GameUserData*)((*ii)->m_pClientExtraData))->m_unUserGameID)
                            if(pClientInfo->m_SocketContext.nSocketID == (*ii)->m_SocketContext.nSocketID)
                            {
                                (*ii)->ChangeGroupStatus(_ClientGroupStatus::GroupStatus_Playing);
                                continue;
                            }
                            else
                            {
                                if((*ii)->m_ClientGroupStatus == _ClientGroupStatus::GroupStatus_Playing)
                                    continue;
                                else
                                {
                                    uninitCount++;
                                }
                            }
                        }

                        if(uninitCount == 0)
                        {
                            Info(tr("[GameServer]房间游戏开始:%1(%2),%3").arg(((_GameGroup*)pGroup->m_pClientsGroupExtraData)->m_nGroupID).arg(pGroup->m_uuid.toString()).arg(pGroup->m_mapAllClients.count()));
                            pGameGroup->GameStart();
                        }
                        else
                            Debug(tr("[GameServer]还缺客户Init:%1").arg(uninitCount));
                        */
                        if(pClientInfo->m_ClientGroupStatus == GroupStatus_ReJoining)
                        {
                            pGameGroup->SendGameSyncAllData(pClientInfo);
                            pGameGroup->SendGameFrameData(false);
                        }
                        else
                        {
                            pGameGroup->SendGameSyncAllData(pClientInfo);
                        }
                    }
                    break;

                //游戏结束
                case GAME_DATA_GAMEOVER:
                    {
                        qint16 status;        //是否是强制结束的
                        qint32 code;        //是否是强制结束的
                        dsData >> status >> code;

                        if(pClientInfo == nullptr)
                            break;

                        //if(gamestatus)    //客户端主动发送扣的分数
                        //    UpdateScore(pClientInfo);

                        if(pGroup == nullptr)   //单人
                        {
                            pClientInfo->ChangeGroupStatus(GroupStatus_Nothing);
                            Info(tr("[GameServer]单人游戏结束:%1,%2,%3").arg(pGameUserData->m_strNickName).arg(status).arg(code));
                        }
                        else    //联网
                        {
                            Debug(tr("[GameServer]联网游戏结束:%1,%2,%3").arg(pGameUserData->m_strNickName).arg(status).arg(code));
                            pGameGroup->OverGame((GameModel::_GameStatus)status, code, pClientInfo);
                            //pGameUserData->ChangeGroupStatus(GroupStatus_Waiting);    //overGame中切换
                        }
                    }
                    break;



                //转发游戏消息
                case GAME_DATA_TRANSFER_DATA:
                    {
                        quint32 targetUserGameID;
                        QVariantMap data;
                        dsData >> targetUserGameID >> data;
                        qDebug() << tr("[GameServer]收到 %1 Data:").arg(pGameUserData->m_strNickName) << (data);

                        if(pGroup == nullptr)
                        {
                            Critical(tr("[!GameServer]%1 GAME_DATA_TRANSFER_DATA 没有房间").arg(pGameUserData->m_strNickName));
                        }
                        else
                        {
                            _ClientInfo *pTargetClientInfo = m_hashAllClientInfo.value(targetUserGameID, nullptr);
                            if(pTargetClientInfo != nullptr)
                                pGameGroup->GameTransferData(data, pTargetClientInfo, pClientInfo);
                        }
                        //baData.remove(0, dsData.device()->pos());
                    }
                    break;

                //转发游戏帧
                case GAME_DATA_FRAME_DATA:
                    {
                        qint32 randomNumberID;
                        qint32 randomNumberPoint;
                        quint32 frameIndex;
                        QVariantMap frame;
                        dsData >> randomNumberID >> randomNumberPoint >> frameIndex >> frame;
                        qDebug() << tr("[GameServer]收到 %1 Frame:").arg(pGameUserData->m_strNickName) << (frame);

                        if(pGroup == nullptr)
                        {
                            Critical(tr("[!GameServer]%1 GAME_DATA_FRAME_DATA 没有房间").arg(pGameUserData->m_strNickName));
                        }
                        else
                        {
                            pGameGroup->GameFrameData(randomNumberID, randomNumberPoint, frameIndex, frame, pClientInfo);
                        }
                        //baData.remove(0, dsData.device()->pos());
                    }
                    break;
                //转发游戏同步数据（一帧）
                case GAME_DATA_SYNC_DATA:
                    {
                        QVariantMap data;
                        dsData >> data;
                        qDebug() << tr("[GameServer]收到 %1 SyncData:").arg(pGameUserData->m_strNickName) << (data);

                        if(pGroup == nullptr)
                        {
                            Critical(tr("[!GameServer]%1 GAME_DATA_SYNC_DATA 没有房间").arg(pGameUserData->m_strNickName));
                        }
                        else
                        {
                            pGameGroup->GameSyncData(data, pClientInfo);
                        }
                        //baData.remove(0, dsData.device()->pos());
                    }
                    break;
                //转发游戏全部数据
                case GAME_DATA_SYNC_ALLDATA:
                    {
                        qint32 randomNumberPoint;
                        QVariantMap data;
                        dsData >> randomNumberPoint >> data;
                        qDebug() << tr("[GameServer]收到 %1 AllSyncData:").arg(pGameUserData->m_strNickName) << (data);

                        if(pGroup == nullptr)
                        {
                            Critical(tr("[!GameServer]%1 GAME_DATA_SYNC_ALLDATA 没有房间").arg(pGameUserData->m_strNickName));
                        }
                        else
                        {
                            pGameGroup->GameSyncAllData(data, randomNumberPoint, pClientInfo);
                        }
                        //baData.remove(0, dsData.device()->pos());
                    }
                    break;

                /*case GAME_DATA_TRANSFER_CHUPAI:
                    {
                    }
                    break;


                case GAME_DATA_GAMESTART:
                    {
                        //传递所有武将信息！！！
                        dsData >> netType;
                        pGroup->m_nMyID = netType;
                        dsData >> netType;
                        pGroup->m_nPlayerCount = netType;
                        dsData>>pGroup->m_bMaster;

                        QList<qint16> playerTypeList;
                        dsData>>playerTypeList;

                        int i = 0;
                        for(i = 0; i < playerTypeList.count(); i++)
                        {
                            pGroup->m_arrayPlayer[i].m_eJiaoSe = (_Player::JiaoSe)playerTypeList[i];
                        }
                        / *
                        QList<qint16>::iterator ii;
                        for (ii = playerTypeList.begin(); ii != playerTypeList.end(); ++ii)
                        {
                               pGroup->m_arrayPlayer[i].iJiaoSe = *ii;
                        }* /

                        //pGroup->netPlay = true;

                        qDebug()<<"StartGame:"
                               <<pGroup->m_nMyID
                              <<pGroup->m_nPlayerCount
                             <<pGroup->m_bMaster;

                        //StartGame(pGroup->m_nPlayerCount,1,1,0,true);
                    }
                    break;
                case GAME_DATA_:
                    {
                        dsData >> netType;
                        //GameOver((GameCore::_GameStatus)netType);
                    }
                    break;
                */

                default:
                    Critical(tr("[!GameServer]GAME_DATA ERROR:%1").arg(netType));
                    break;
                }
            }
            break;


        default:
            Critical(tr("[!GameServer]数据总类型未识别:%1").arg(netType));
            break;
        }
    }
    return;
}

void GameServer::onUDPReadyRead(QByteArray baData, SOCKADDR_IN addrinClient)
{
    //qDebug()<<"ThreadId:"<<::GetCurrentThreadId();

    /*QString ip;
    ip.sprintf("%d.%d.%d.%d",
               addrinClient.sin_addr.S_un.S_addr & 0xff,
               (addrinClient.sin_addr.S_un.S_addr & 0xff00) >> 8,
               (addrinClient.sin_addr.S_un.S_addr & 0xff0000) >> 16,
               (addrinClient.sin_addr.S_un.S_addr & 0xff000000) >> 24
               );*/

    Info(tr("[GameServer]onUDPReadyRead:%1(%2:%3)").arg(baData.constData()).arg(inet_ntoa(addrinClient.sin_addr)).arg(ntohs(addrinClient.sin_port)));
    Debug(tr("[GameServer]onUDPReadyRead:%1(%2:%3)").arg(baData.constData()).arg(inet_ntoa(addrinClient.sin_addr)).arg(ntohs(addrinClient.sin_port)));

    m_pUDPIOCPModel->SendTo(baData.constData(), baData.length(), addrinClient.sin_addr.s_addr, ntohs(addrinClient.sin_port));
    m_pUDPIOCPModel->sendTo(baData.prepend("server:"), addrinClient.sin_addr.s_addr, ntohs(addrinClient.sin_port));
}










/*
bool GameServer::UpdateScore(_ClientInfo *pClientInfo, bool bNetPlay, qint16 achieve, qint32 scoreAdd)
{
    if(pClientInfo == nullptr)
        return false;

    _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

    if(scoreAdd == 0)
    {
        //Info(tr("[GameServer]%1 积分为0，不记录").arg(((_GameUserData*)pClientInfo->m_pClientExtraData)->m_strNickName));
        //return false;
    }

    //如果游戏中断网
    if(achieve == 0)
    {
        achieve = 3;    //设定为逃跑

        if(bNetPlay)    //如果联网游戏中
            scoreAdd = -100;
    }

    //int ret = m_DatabaseSwap.updateUserScore(((_GameUserData*)pClientInfo->m_pClientExtraData)->m_unUserGameID, score);
    QMetaObject::invokeMethod(m_pDatabase,"sl_UpdateScore"
                              ,Qt::AutoConnection
                              //,Q_RETURN_ARG(QVariant, v)
                              ,Q_ARG(quint32, pGameUserData->m_unUserGameID)
                              ,Q_ARG(qint16, achieve)
                              ,Q_ARG(qint32, scoreAdd)
                              ,Q_ARG(QByteArray, m_Server.m_IOCPModel.newSendData())
                              ,Q_ARG(_SocketInfo::_SocketContext, pClientInfo->m_SocketContext)
                              );

    Info(tr("[GameServer]%1 增加积分:%2").arg(((_GameUserData*)pClientInfo->m_pClientExtraData)->m_strNickName).arg(scoreAdd));

    return true;
}
*/
